]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68000 non-prefetch mode is also cycle-accurate (does not include wait state memory...
authorToni Wilen <twilen@winuae.net>
Thu, 13 Feb 2020 19:24:50 +0000 (21:24 +0200)
committerToni Wilen <twilen@winuae.net>
Thu, 13 Feb 2020 19:24:50 +0000 (21:24 +0200)
gencpu.cpp
include/newcpu.h
newcpu.cpp

index dc4afd7da676c4ed381cb63807d9debbaa92fae9..f7593a3e9794b53b75dd01ccfd2cb79c330dde4e 100644 (file)
 static FILE *headerfile;
 static FILE *stblfile;
 
+// optional settings
+static int using_always_dynamic_cycles = 1;
+static int using_bus_error = 1;
+
+
 static int using_prefetch, using_indirect, using_mmu;
 static int using_prefetch_020, using_ce020;
 static int using_exception_3;
-static int using_bus_error;
 static int using_ce;
 static int using_tracer;
 static int using_waitstates;
@@ -48,7 +52,10 @@ static int using_debugmem;
 static int using_test;
 static int need_special_fixup;
 static int cpu_level, cpu_generic;
-static int count_read, count_write, count_cycles, count_ncycles;
+static int count_readp;
+static int count_readw, count_readl;
+static int count_writew, count_writel;
+static int count_cycles, count_ncycles;
 static int count_cycles_ce020;
 static int count_read_ea, count_write_ea, count_cycles_ea;
 static const char *mmu_postfix, *xfc_postfix;
@@ -56,6 +63,7 @@ static int memory_cycle_cnt;
 static int did_prefetch;
 static int ipl_fetched;
 static int opcode_nextcopy;
+static int do_always_dynamic_cycles;
 
 static int optimized_flags;
 
@@ -184,7 +192,7 @@ static void out(const char *format, ...)
                        for (int i = 0; i < brace_level; i++) {
                                printf("\t");
                        }
-                       printf(outbuf2);
+                       printf("%s", outbuf2);
 
                        ps = outbuf2;
                        while (*ps) {
@@ -262,8 +270,8 @@ static int m68k_pc_offset, m68k_pc_offset_old;
 static int m68k_pc_total;
 static int exception_pc_offset;
 static int branch_inst;
-static int insn_n_cycles, insn_n_cycles020;
 static int ir2irc;
+static int insn_n_cycles;
 
 static int tail_ce020, total_ce020, head_in_ea_ce020;
 static bool head_ce020_cycs_done, tail_ce020_done;
@@ -273,26 +281,45 @@ static bool no_prefetch_ce020;
 static bool got_ea_ce020;
 
 // 68010-40 needs different implementation than 68060
-static void next_level_060_to_040(void)
+static bool next_level_060_to_040(void)
 {
        if (cpu_level >= 5) {
-               if (next_cpu_level < 5)
+               if (next_cpu_level < 5) {
                        next_cpu_level = 5 - 1;
+                       return true;
+               }
        }
+       return false;
 }
 // 68010-30 needs different implementation than 68040/060
-static void next_level_040_to_030(void)
+static bool next_level_040_to_030(void)
 {
        if (cpu_level >= 4) {
-               if (next_cpu_level < 4)
+               if (next_cpu_level < 4) {
                        next_cpu_level = 4 - 1;
+                       return true;
+               }
        }
+       return false;
+}
+// 68000-010 needs different implementation than 68020+
+static bool next_level_020_to_010(void)
+{
+       if (cpu_level >= 2) {
+               if (next_cpu_level < 2) {
+                       next_cpu_level = 2 - 1;
+                       return true;
+               }
+       }
+       return false;
 }
 // 68000 <> 68010
-static void next_level_000(void)
+static bool next_level_000(void)
 {
-       if (next_cpu_level < 0)
+       if (next_cpu_level < 0) {
                next_cpu_level = 0;
+       }
+       return false;
 }
 
 static void fpulimit (void)
@@ -301,21 +328,29 @@ static void fpulimit (void)
        set_fpulimit = 1;
 }
 
-static int s_count_read, s_count_write, s_count_cycles, s_count_ncycles;
+static int s_count_readw, s_count_readl;
+static int s_count_writew, s_count_writel;
+static int s_count_cycles, s_count_ncycles, s_insn_cycles;
 
 static void push_ins_cnt(void)
 {
-       s_count_read = count_read;
-       s_count_write = count_write;
+       s_count_readw = count_readw;
+       s_count_readl = count_readl;
+       s_count_writew = count_writew;
+       s_count_writel = count_writel;
        s_count_cycles = count_cycles;
        s_count_ncycles = count_ncycles;
+       s_insn_cycles = insn_n_cycles;
 }
 static void pop_ins_cnt(void)
 {
-       count_read = s_count_read;
-       count_write = s_count_write;
+       count_readw = s_count_readw;
+       count_readl = s_count_readl;
+       count_writew = s_count_writew;
+       count_writel = s_count_writel;
        count_cycles = s_count_cycles;
        count_ncycles = s_count_ncycles;
+       insn_n_cycles = s_insn_cycles;
 }
 
 static bool needmmufixup(void)
@@ -496,10 +531,17 @@ static void returncycles(int cycles)
                out("return;\n");
                return;
        }
-       if (using_simple_cycles)
+       if (do_always_dynamic_cycles) {
+               int total = count_readl + count_readw + count_writel + count_writew - count_readp;
+               if (!total)
+                       total++;
+               out("return (%d * CYCLE_UNIT / 2 + count_cycles) | (((%d * 4 * CYCLE_UNIT / 2 + count_cycles) * 3) << 16);\n", cycles,
+                       total);
+       } else if (using_simple_cycles) {
                out("return %d * CYCLE_UNIT / 2 + count_cycles;\n", cycles);
-       else
+       } else {
                out("return %d * CYCLE_UNIT / 2;\n", cycles);
+       }
 }
 
 static void write_return_cycles_none(void)
@@ -526,17 +568,18 @@ static void write_return_cycles2(int end, int no4)
                        }
                } else {
                        int cc = count_cycles;
-                       if (count_read + count_write + cc == 0 && !no4)
+                       if (count_readw + count_writew + count_readl + count_writel + cc == 0 && !no4)
                                cc = 4;
-                       returncycles((count_read + count_write) * 4 + cc);
+                       returncycles((count_readw + count_writew) * 4 + (count_readl + count_writel) * 8 + cc);
                        if (end) {
                                out("}\n");
                                out("/* %d%s (%d/%d)",
-                                       (count_read + count_write) * 4 + cc, count_ncycles ? "+" : "", count_read, count_write);
+                                       (count_readw + count_writew) * 4 + (count_readl + count_writel) * 8 + cc, count_ncycles ? "+" : "",
+                                       count_readw + count_readl * 2, count_writew + count_writel * 2);
                                out(" */\n");
                        }
                }
-       } else if (count_read + count_write) {
+       } else {
                if (end < 0) {
                        if (using_ce020) {
                                out("return;\n");
@@ -544,20 +587,11 @@ static void write_return_cycles2(int end, int no4)
                                out("return 0;\n");
                        }
                } else {
-                       returncycles((count_read + count_write) * 4 + count_cycles);
-                       if (end) {
-                               out("}\n");
-                       }
-               }
-       } else {
-               if (end < 0) {
-                       if (using_ce020) {
-                               out("return;\n");
+                       if (!using_prefetch && !using_prefetch_020) {
+                               returncycles((count_readw + count_writew) * 4 + (count_readl + count_writel) * 8 + insn_n_cycles);
                        } else {
-                               out("return 0;\n");
+                               returncycles((count_readw + count_writew) * 4 + (count_readl + count_writel) * 8 + count_cycles);
                        }
-               } else {
-                       returncycles(insn_n_cycles);
                        if (end) {
                                out("}\n");
                        }
@@ -603,14 +637,14 @@ static void addcycles_ce020 (const char *name, int head, int tail, int cycles, i
 
 static void addcycles000_nonces(const char *sc)
 {
-       if (using_simple_cycles) {
+       if (using_simple_cycles || do_always_dynamic_cycles) {
                out("count_cycles += (%s) * CYCLE_UNIT / 2;\n", sc);
                count_ncycles++;
        }
 }
 static void addcycles000_nonce(int c)
 {
-       if (using_simple_cycles) {
+       if (using_simple_cycles || do_always_dynamic_cycles) {
                out("count_cycles += %d * CYCLE_UNIT / 2;\n", c);
                count_ncycles++;
        }
@@ -629,6 +663,7 @@ static void addcycles000(int cycles)
                out("%s(%d);\n", do_cycles, cycles);
        }
        count_cycles += cycles;
+       insn_n_cycles += cycles;
 }
 static void addcycles000_2(int cycles)
 {
@@ -636,6 +671,7 @@ static void addcycles000_2(int cycles)
                out("%s(%d);\n", do_cycles, cycles);
        }
        count_cycles += cycles;
+       insn_n_cycles += cycles;
 }
 
 static void addcycles000_3(void)
@@ -756,12 +792,33 @@ static void gen_nextilong2 (const char *type, const char *name, int flags, int m
                        out("%s = %s(%d);\n", name, prefetch_long, r);
                else
                        out("%s = %s(%d);\n", name, prefetch_long, r);
-               count_read += 2;
+               count_readl++;
        } else if (using_ce) {
                /* we must do this because execution order of (something | something2) is not defined */
                if (flags & GF_NOREFILL) {
                        out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
-                       count_read++;
+                       count_readw++;
+                       out("%s |= regs.irc;\n", name);
+                       check_bus_error_ins(r + 2);
+                       do_instruction_buserror();
+                       strcpy(bus_error_code, bus_error_code2);
+                       bus_error_code2[0] = 0;
+                       bus_error_text[0] = 0;
+               } else {
+                       out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
+                       count_readw++;
+                       check_bus_error_ins(r + 2);
+                       do_instruction_buserror();
+                       strcpy(bus_error_code, bus_error_code2);
+                       bus_error_code2[0] = 0;
+                       out("%s |= %s(%d);\n", name, prefetch_word, r + 4);
+                       count_readw++;
+                       check_bus_error_ins(r + 4);
+               }
+       } else if (using_prefetch) {
+               if (flags & GF_NOREFILL) {
+                       out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
+                       count_readw++;
                        out("%s |= regs.irc;\n", name);
                        check_bus_error_ins(r + 2);
                        do_instruction_buserror();
@@ -770,43 +827,24 @@ static void gen_nextilong2 (const char *type, const char *name, int flags, int m
                        bus_error_text[0] = 0;
                } else {
                        out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
-                       count_read++;
+                       count_readw++;
                        check_bus_error_ins(r + 2);
                        do_instruction_buserror();
                        strcpy(bus_error_code, bus_error_code2);
                        bus_error_code2[0] = 0;
                        out("%s |= %s(%d);\n", name, prefetch_word, r + 4);
-                       count_read++;
+                       count_readw++;
                        check_bus_error_ins(r + 4);
                }
        } else {
-               if (using_prefetch) {
-                       if (flags & GF_NOREFILL) {
-                               out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
-                               count_read++;
-                               insn_n_cycles += 4;
-                               out("%s |= regs.irc;\n", name);
-                               check_bus_error_ins(r + 2);
-                               do_instruction_buserror();
-                               strcpy(bus_error_code, bus_error_code2);
-                               bus_error_code2[0] = 0;
-                               bus_error_text[0] = 0;
-                       } else {
-                               out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
-                               count_read++;
-                               insn_n_cycles += 4;
-                               check_bus_error_ins(r + 2);
-                               do_instruction_buserror();
-                               strcpy(bus_error_code, bus_error_code2);
-                               bus_error_code2[0] = 0;
-                               out("%s |= %s(%d);\n", name, prefetch_word, r + 4);
-                               count_read++;
-                               check_bus_error_ins(r + 4);
-                       }
+               if (flags & GF_NOREFILL) {
+                       count_readw++;
+                       count_readp++;
                } else {
-                       insn_n_cycles += 8;
-                       out("%s = %s(%d);\n", name, prefetch_long, r);
+                       count_readl++;
+                       count_readp++;
                }
+               out("%s = %s(%d);\n", name, prefetch_long, r);
        }
 }
 static void gen_nextilong (const char *type, const char *name, int flags)
@@ -829,28 +867,28 @@ static const char *gen_nextiword (int flags)
                        sprintf(buffer, "%s(%d)", prefetch_word, r);
                else
                        sprintf(buffer, "%s(%d)", prefetch_word, r);
-               count_read++;
+               count_readw++;
        } else if (using_ce) {
                if (flags & GF_NOREFILL) {
                        strcpy(buffer, "regs.irc");
                } else {
                        sprintf(buffer, "%s(%d)", prefetch_word, r + 2);
-                       count_read++;
+                       count_readw++;
                        check_bus_error_ins(r + 2);
                }
-       } else {
-               if (using_prefetch) {
-                       if (flags & GF_NOREFILL) {
-                               strcpy(buffer, "regs.irc");
-                       } else {
-                               sprintf(buffer, "%s(%d)", prefetch_word, r + 2);
-                               count_read++;
-                               insn_n_cycles += 4;
-                               check_bus_error_ins(r + 2);
-                       }
+       } else if (using_prefetch) {
+               if (flags & GF_NOREFILL) {
+                       strcpy(buffer, "regs.irc");
                } else {
-                       sprintf(buffer, "%s(%d)", prefetch_word, r);
-                       insn_n_cycles += 4;
+                       sprintf(buffer, "%s(%d)", prefetch_word, r + 2);
+                       count_readw++;
+                       check_bus_error_ins(r + 2);
+               }
+       } else {
+               sprintf(buffer, "%s(%d)", prefetch_word, r);
+               if (!(flags & GF_NOREFILL)) {
+                       count_readw++;
+                       count_readp++;
                        check_bus_error_ins(r);
                }
        }
@@ -870,29 +908,28 @@ static const char *gen_nextibyte (int flags)
                        sprintf(buffer, "(uae_u8)%s(%d)", prefetch_word, r);
                else
                        sprintf(buffer, "(uae_u8)%s(%d)", prefetch_word, r);
-               count_read++;
+               count_readw++;
        } else if (using_ce) {
                if (flags & GF_NOREFILL) {
                        strcpy(buffer, "(uae_u8)regs.irc");
                } else {
                        sprintf(buffer, "(uae_u8)%s(%d)", prefetch_word, r + 2);
-                       count_read++;
+                       count_readw++;
                        check_bus_error_ins(r + 2);
                }
-       } else {
-               insn_n_cycles += 4;
-               if (using_prefetch) {
-                       if (flags & GF_NOREFILL) {
-                               strcpy(buffer, "(uae_u8)regs.irc");
-                       } else {
-                               sprintf(buffer, "(uae_u8)%s(%d)", prefetch_word, r + 2);
-                               count_read++;
-                               insn_n_cycles += 4;
-                               check_bus_error_ins(r + 2);
-                       }
+       } else if (using_prefetch) {
+               if (flags & GF_NOREFILL) {
+                       strcpy(buffer, "(uae_u8)regs.irc");
                } else {
-                       sprintf(buffer, "%s(%d)", srcbi, r);
-                       insn_n_cycles += 4;
+                       sprintf(buffer, "(uae_u8)%s(%d)", prefetch_word, r + 2);
+                       count_readw++;
+                       check_bus_error_ins(r + 2);
+               }
+       } else {
+               sprintf(buffer, "%s(%d)", srcbi, r);
+               if (!(flags & GF_NOREFILL)) {
+                       count_readw++;
+                       count_readp++;
                        check_bus_error_ins(r);
                }
        }
@@ -984,26 +1021,26 @@ static void fill_prefetch_bcc(void)
        }
 
        out("%s(%d);\n", prefetch_word, m68k_pc_offset + 2);
-       count_read++;
-       insn_n_cycles += 4;
+       count_readw++;
        check_prefetch_bus_error(m68k_pc_offset + 2, 0);
        did_prefetch = 1;
        ir2irc = 0;
 }
 
-static void fill_prefetch_1 (int o)
+static void fill_prefetch_1(int o)
 {
        if (using_prefetch) {
                out("%s(%d);\n", prefetch_word, o);
                if (!loopmode || using_ce) {
-                       count_read++;
-                       insn_n_cycles += 4;
+                       count_readw++;
                } else {
                        addcycles000_nonce(4);
                }
                check_prefetch_bus_error(o, 0);
                did_prefetch = 1;
                ir2irc = 0;
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -1012,11 +1049,12 @@ static void fill_prefetch_1_empty(int o)
 {
        if (using_prefetch) {
                out("%s(%d);\n", prefetch_word, o);
-               count_read++;
-               insn_n_cycles += 4;
+               count_readw++;
                check_prefetch_bus_error(o ? -2 : -1, 0);
                did_prefetch = 1;
                ir2irc = 0;
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -1034,6 +1072,8 @@ static void fill_prefetch_full_2 (void)
                        out("fill_prefetch_030();\n");
                else if (cpu_level == 2)
                        out("fill_prefetch_020();\n");
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -1064,11 +1104,13 @@ static void fill_prefetch_full_ntx(int beopcode)
                        out("fill_prefetch_030_ntx();\n");
                else if (cpu_level == 2)
                        out("fill_prefetch_020_ntx();\n");
+       } else {
+               insn_n_cycles += 2 * 4;
        }
 }
 static void check_trace(void)
 {
-       if (!using_prefetch && !using_ce)
+       if (!using_prefetch && !using_ce && cpu_level >= 2)
                out("if(regs.t0) check_t0_trace();\n");
 }
 
@@ -1110,18 +1152,29 @@ static void fill_prefetch_full(int beopcode)
                else if (cpu_level == 2)
                        out("fill_prefetch_020();\n");
        } else if (!using_prefetch_020 && cpu_level >= 2) {
+               insn_n_cycles += 2 * 4;
                check_trace();
+       } else {
+               insn_n_cycles += 2 * 4;
        }
 }
 
 static void fill_prefetch_full_000_special(const char *format, ...)
 {
-       if (!using_prefetch)
+       if (!using_prefetch) {
+               if (format && cpu_level <= 1) {
+                       char outbuf[256];
+                       va_list parms;
+                       va_start(parms, format);
+                       _vsnprintf(outbuf, sizeof(outbuf) - 1, format, parms);
+                       va_end(parms);
+                       out(outbuf);
+               }
                return;
+       }
 
        out("%s(%d);\n", prefetch_word, 0);
-       count_read++;
-       insn_n_cycles += 2;
+       count_readw++;
        check_prefetch_bus_error(-1, -1);
        irc2ir();
        if (using_bus_error) {
@@ -1144,8 +1197,7 @@ static void fill_prefetch_full_000_special(const char *format, ...)
                out(outbuf);
        }
        out("%s(%d);\n", prefetch_word, 2);
-       count_read++;
-       insn_n_cycles += 2;
+       count_readw++;
        check_prefetch_bus_error(-2, -1);
        did_prefetch = 1;
        ir2irc = 0;
@@ -1154,16 +1206,18 @@ static void fill_prefetch_full_000_special(const char *format, ...)
 // 68000 and 68010 only
 static void fill_prefetch_full_000(int beopcode)
 {
-       if (!using_prefetch)
-               return;
-       fill_prefetch_full(beopcode);
+       if (using_prefetch) {
+               fill_prefetch_full(beopcode);
+       } else {
+               insn_n_cycles += 2 * 4;
+       }
 }
 
 // 68020+
 static void fill_prefetch_full_020 (void)
 {
        if (!using_prefetch_020) {
-               if (!using_prefetch && !using_ce)
+               if (!using_prefetch && !using_ce && cpu_level >= 2)
                        out("if(regs.t0) check_t0_trace();\n");
                return;
        }
@@ -1172,14 +1226,15 @@ static void fill_prefetch_full_020 (void)
 
 static void fill_prefetch_0 (void)
 {
-       if (!using_prefetch)
-               return;
-       out("%s(0);\n", prefetch_word);
-       count_read++;
-       insn_n_cycles += 4;
-       check_prefetch_bus_error(0, 0);
-       did_prefetch = 1;
-       ir2irc = 0;
+       if (using_prefetch) {
+               out("%s(0);\n", prefetch_word);
+               count_readw++;
+               check_prefetch_bus_error(0, 0);
+               did_prefetch = 1;
+               ir2irc = 0;
+       } else {
+               insn_n_cycles += 4;
+       }
 }
 
 static void loopmode_start(void)
@@ -1315,6 +1370,8 @@ static void fill_prefetch_next_noopcodecopy(const char *format, ...)
                        copy_opcode();
                }
                loopmode_end();
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -1328,6 +1385,8 @@ static void fill_prefetch_next(void)
                }
                fill_prefetch_1(m68k_pc_offset + 2);
                loopmode_end();
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -1345,6 +1404,8 @@ static void fill_prefetch_next_t(void)
                }
                fill_prefetch_1(m68k_pc_offset + 2);
                loopmode_end();
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -1368,6 +1429,8 @@ static void fill_prefetch_next_extra(const char *cond, const char *format, ...)
                }
                fill_prefetch_1(m68k_pc_offset + 2);
                loopmode_end();
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -1397,6 +1460,8 @@ static void fill_prefetch_next_after(int copy, const char *format, ...)
                        }
                }
                loopmode_end();
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -1410,11 +1475,9 @@ static void fill_prefetch_next_skipopcode(void)
                        }
                }
                fill_prefetch_1(m68k_pc_offset + 2);
+       } else {
+               insn_n_cycles += 4;
        }
-       //      if (using_prefetch_020) {
-       //              out("%s(%d);\n", prefetch_word, m68k_pc_offset);
-       //              did_prefetch = 1;
-       //      }
 }
 
 
@@ -1423,6 +1486,8 @@ static void fill_prefetch_next_empty(void)
        if (using_prefetch) {
                irc2ir();
                fill_prefetch_1_empty(m68k_pc_offset + 2);
+       } else {
+               insn_n_cycles += 4;
        }
 }
 
@@ -2329,7 +2394,7 @@ static void addcycles_ea_ce020 (const char *ea, int h, int t, int c)
 #define SETCE020(h2,t2,c2) { h = h2; t = t2; c = c2; }
 #define SETCE020H(h2,t2,c2) { h = h2; oph = curi ? curi->head : 0; t = t2; c = c2; }
 
-static int gence020cycles_fiea (instr *curi, wordsizes ssize, amodes dmode)
+static int gence020cycles_fiea (struct instr *curi, wordsizes ssize, amodes dmode)
 {
        bool l = ssize == sz_long;
        int h = 0, t = 0, c = 0, oph = 0;
@@ -2392,7 +2457,7 @@ static int gence020cycles_fiea (instr *curi, wordsizes ssize, amodes dmode)
 }
 
 
-static int gence020cycles_ciea (instr *curi, wordsizes ssize, amodes dmode)
+static int gence020cycles_ciea (struct instr *curi, wordsizes ssize, amodes dmode)
 {
        int h = 0, t = 0, c = 0, oph = 0;
        bool l = ssize == sz_long;
@@ -2505,7 +2570,7 @@ static int gence020cycles_fea (amodes mode)
        return 0;
 }
 
-static int gence020cycles_cea (instr *curi, amodes mode)
+static int gence020cycles_cea (struct instr *curi, amodes mode)
 {
        int h = 0, t = 0, c = 0, oph = 0;
        switch (mode)
@@ -2542,7 +2607,7 @@ static int gence020cycles_cea (instr *curi, amodes mode)
        return oph;
 }
 
-static int gence020cycles_jea (instr *curi, amodes mode)
+static int gence020cycles_jea (struct instr *curi, amodes mode)
 {
        int h = 0, t = 0, c = 0, oph = 0;
        switch (mode)
@@ -2928,14 +2993,10 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        term();
                }
                if (flags & GF_NOFETCH) {
-                       if (using_prefetch) {
-                               addcycles000(4);
-                       }
-                       insn_n_cycles += 2;
+                       addcycles000(4);
                        count_cycles_ea += 2;
                } else if (!(flags & GF_APDI)) {
                        addcycles000(2);
-                       insn_n_cycles += 2;
                        count_cycles_ea += 2;
                        pc_68000_offset_fetch += 2;
                        if (size == sz_long)
@@ -2978,7 +3039,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                } else {
                        if (!(flags & GF_AD8R) && !(flags & GF_NOFETCH) && !(flags & GF_CLR68010)) {
                                addcycles000(2);
-                               insn_n_cycles += 2;
                                count_cycles_ea += 2;
                        }
                        if ((flags & GF_NOREFILL) && using_prefetch) {
@@ -2990,12 +3050,10 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                }
                if ((flags & GF_NOFETCH) && using_prefetch) {
                        addcycles000(4);
-                       insn_n_cycles += 4;
                        count_cycles_ea += 4;
                }
                if ((flags & GF_CLR68010) && using_prefetch) {
                        addcycles000(4);
-                       insn_n_cycles += 4;
                        count_cycles_ea += 4;
                }
                addr = true;
@@ -3025,7 +3083,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        out("tmppc = %s + %d;\n", getpc, m68k_pc_offset);
                        if (!(flags & GF_PC8R)) {
                                addcycles000(2);
-                               insn_n_cycles += 2;
                                count_cycles_ea += 2;
                        }
                        if ((flags & GF_NOREFILL) && using_prefetch) {
@@ -3057,7 +3114,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                // fetch immediate address
                if (getv != 1)
                        term();
-               insn_n_cycles020++;
                switch (size) {
                case sz_byte:
                        out("uae_s8 %s = %s;\n", name, gen_nextibyte (flags));
@@ -3295,37 +3351,34 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                if (using_mmu) {
                        if (flags & GF_FC) {
                                switch (size) {
-                               case sz_byte: insn_n_cycles += 4; out("uae_s8 %s = sfc%s_get_byte%s(%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
-                               case sz_word: insn_n_cycles += 4; out("uae_s16 %s = sfc%s_get_word%s(%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
-                               case sz_long: insn_n_cycles += 8; out("uae_s32 %s = sfc%s_get_long%s(%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
+                               case sz_byte: count_readw++; out("uae_s8 %s = sfc%s_get_byte%s(%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
+                               case sz_word: count_readw++; out("uae_s16 %s = sfc%s_get_word%s(%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
+                               case sz_long: count_readl++; out("uae_s32 %s = sfc%s_get_long%s(%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
                                default: term();
                                }
                        } else {
                                switch (size) {
-                               case sz_byte: insn_n_cycles += 4; out("uae_s8 %s = %s(%sa);\n", name, (flags & GF_LRMW) ? srcblrmw : (rmw ? srcbrmw : srcb), name); break;
-                               case sz_word: insn_n_cycles += 4; out("uae_s16 %s = %s(%sa);\n", name, (flags & GF_LRMW) ? srcwlrmw : (rmw ? srcwrmw : srcw), name); break;
-                               case sz_long: insn_n_cycles += 8; out("uae_s32 %s = %s(%sa);\n", name, (flags & GF_LRMW) ? srcllrmw : (rmw ? srclrmw : srcl), name); break;
+                               case sz_byte: count_readw++; out("uae_s8 %s = %s(%sa);\n", name, (flags & GF_LRMW) ? srcblrmw : (rmw ? srcbrmw : srcb), name); break;
+                               case sz_word: count_readw++; out("uae_s16 %s = %s(%sa);\n", name, (flags & GF_LRMW) ? srcwlrmw : (rmw ? srcwrmw : srcw), name); break;
+                               case sz_long: count_readl++; out("uae_s32 %s = %s(%sa);\n", name, (flags & GF_LRMW) ? srcllrmw : (rmw ? srclrmw : srcl), name); break;
                                default: term();
                                }
                        }
                } else if (using_ce020 || using_prefetch_020) {
                        switch (size) {
                        case sz_byte:
-                               insn_n_cycles += 4;
                                out("uae_s8 %s = %s(%sa);\n", name, srcbx, name);
-                               count_read++;
+                               count_readw++;
                                check_bus_error(name, 0, 0, 0, NULL, 1);
                                break;
                        case sz_word:
-                               insn_n_cycles += 4;
                                out("uae_s16 %s = %s(%sa);\n", name, srcwx, name);
-                               count_read++;
+                               count_readw++;
                                check_bus_error(name, 0, 0, 1, NULL, 1);
                                break;
                        case sz_long:
-                               insn_n_cycles += 8;
                                out("uae_s32 %s = %s(%sa);\n", name, srclx, name);
-                               count_read += 2;
+                               count_readl++;
                                check_bus_error(name, 0, 0, 2, NULL, 1);
                                break;
                        default: term();
@@ -3334,36 +3387,33 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        switch (size) {
                        case sz_byte:
                        {
-                               insn_n_cycles += 4;
                                out("uae_s8 %s = %s(%sa);\n", name, srcbx, name);
-                               count_read++;
+                               count_readw++;
                                check_bus_error(name, 0, 0, 0, NULL, 1);
                                break;
                        }
                        case sz_word:
                        {
-                               insn_n_cycles += 4;
                                out("uae_s16 %s = %s(%sa);\n", name, srcwx, name);
-                               count_read++;
+                               count_readw++;
                                check_bus_error(name, 0, 0, 1, NULL, 1);
                                break;
                        }
                        case sz_long:
                        {
-                               insn_n_cycles += 8;
                                if ((flags & GF_REVERSE) && mode == Apdi) {
                                        out("uae_s32 %s = %s(%sa + 2);\n", name, srcwx, name);
-                                       count_read++;
+                                       count_readw++;
                                        check_bus_error(name, 0, 0, 1, NULL, 1);
                                        out("%s |= %s(%sa) << 16; \n", name, srcwx, name);
-                                       count_read++;
+                                       count_readw++;
                                        check_bus_error(name, -2, 0, 1, NULL, 1);
                                } else {
                                        out("uae_s32 %s = %s(%sa) << 16;\n", name, srcwx, name);
-                                       count_read++;
+                                       count_readw++;
                                        check_bus_error(name, 0, 0, 1, NULL, 1);
                                        out("%s |= %s(%sa + 2); \n", name, srcwx, name);
-                                       count_read++;
+                                       count_readw++;
                                        check_bus_error(name, 2, 0, 1, NULL, 1);
                                }
                                break;
@@ -3373,21 +3423,18 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                } else {
                        switch (size) {
                        case sz_byte:
-                               insn_n_cycles += 4;
                                out("uae_s8 %s = %s(%sa);\n", name, srcbx, name);
-                               count_read++;
+                               count_readw++;
                                check_bus_error(name, 0, 0, 0, NULL, 1);
                                break;
                        case sz_word:
-                               insn_n_cycles += 4;
                                out("uae_s16 %s = %s(%sa);\n", name, srcwx, name);
-                               count_read++;
+                               count_readw++;
                                check_bus_error(name, 0, 0, 1, NULL, 1);
                                break;
                        case sz_long:
-                               insn_n_cycles += 8;
                                out("uae_s32 %s = %s(%sa);\n", name, srclx, name);
-                               count_read += 2;
+                               count_readl++;
                                check_bus_error(name, 0, 0, 2, NULL, 1);
                                break;
                        default: term();
@@ -3430,7 +3477,7 @@ static void genamode2 (amodes mode, const char *reg, wordsizes size, const char
        genamode2x (mode, reg, size, name, getv, movem, flags, -1);
 }
 
-static void genamode(instr *curi, amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem, int flags)
+static void genamode(struct instr *curi, amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem, int flags)
 {
        int oldfixup = mmufixupstate;
        int subhead = 0;
@@ -3459,7 +3506,7 @@ static void genamode(instr *curi, amodes mode, const char *reg, wordsizes size,
                addop_ce020 (curi, subhead, flags);
 }
 
-static void genamode3 (instr *curi, amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem, int flags)
+static void genamode3 (struct instr *curi, amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem, int flags)
 {
        int oldfixup = mmufixupstate;
        genamode2x (mode, reg, size, name, getv, movem, flags, curi ? curi->fetchmode : -1);
@@ -3469,7 +3516,7 @@ static void genamode3 (instr *curi, amodes mode, const char *reg, wordsizes size
        }
 }
 
-static void genamodedual(instr *curi, amodes smode, const char *sreg, wordsizes ssize, const char *sname, int sgetv, int sflags,
+static void genamodedual(struct instr *curi, amodes smode, const char *sreg, wordsizes ssize, const char *sname, int sgetv, int sflags,
                                           amodes dmode, const char *dreg, wordsizes dsize, const char *dname, int dgetv, int dflags)
 {
        int subhead = 0;
@@ -3573,14 +3620,14 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                if (using_mmu) {
                        switch (size) {
                        case sz_byte:
-                               insn_n_cycles += 4;
+                               count_writew++;
                                if (flags & GF_FC)
                                        out("dfc%s_put_byte%s(%sa, %s);\n", mmu_postfix, xfc_postfix, to, from);
                                else
                                        out("%s(%sa, %s);\n", (flags & GF_LRMW) ? dstblrmw : (candormw ? dstbrmw : dstb), to, from);
                                break;
                        case sz_word:
-                               insn_n_cycles += 4;
+                               count_writew++;
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
                                        term();
                                if (flags & GF_FC)
@@ -3589,7 +3636,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        out("%s(%sa, %s);\n", (flags & GF_LRMW) ? dstwlrmw : (candormw ? dstwrmw : dstw), to, from);
                                break;
                        case sz_long:
-                               insn_n_cycles += 8;
+                               count_writel++;
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
                                        term();
                                if (flags & GF_FC)
@@ -3604,21 +3651,21 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                        switch (size) {
                        case sz_byte:
                                out("%s(%sa, %s);\n", dstbx, to, from);
-                               count_write++;
+                               count_writew++;
                                check_bus_error(to, 0, 1, 0, from, 1);
                                break;
                        case sz_word:
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
                                        term();
                                out("%s(%sa, %s);\n", dstwx, to, from);
-                               count_write++;
+                               count_writew++;
                                check_bus_error(to, 0, 1, 1, from, 1);
                                break;
                        case sz_long:
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
                                        term();
                                out("%s(%sa, %s);\n", dstlx, to, from);
-                               count_write += 2;
+                               count_writel++;
                                check_bus_error(to, 0, 1, 2, from, 1);
                                break;
                        default:
@@ -3629,7 +3676,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                        case sz_byte:
                                check_ipl_again();
                                out("x_put_byte(%sa, %s);\n", to, from);
-                               count_write++;
+                               count_writew++;
                                check_bus_error(to, 0, 1, 0, from, 1);
                                break;
                        case sz_word:
@@ -3637,7 +3684,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        term();
                                check_ipl_again();
                                out("x_put_word(%sa, %s);\n", to, from);
-                               count_write++;
+                               count_writew++;
                                check_bus_error(to, 0, 1, 1, from, 1);
                                break;
                        case sz_long:
@@ -3645,7 +3692,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        term();
                                if (store_dir) {
                                        out("%s(%sa + 2, %s);\n", dstwx, to, from);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error(to, 2, 1, 1, from, 1);
                                        check_ipl_again();
                                        if (flags & GF_SECONDWORDSETFLAGS) {
@@ -3654,22 +3701,23 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        // ADDX.L/SUBX.L -(an),-(an) only
                                        if (store_dir > 1) {
                                                fill_prefetch_next_after(0, NULL);
+                                               insn_n_cycles += 4;
                                        }
                                        out("%s(%sa, %s >> 16);\n", dstwx, to, from);
                                        sprintf(tmp, "%s >> 16", from);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error(to, 0, 1, 1, tmp, 1);
                                } else {
                                        out("%s(%sa, %s >> 16);\n", dstwx, to, from);
                                        sprintf(tmp, "%s >> 16", from);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error(to, 0, 1, 1, tmp, 1);
                                        check_ipl_again();
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
                                        out("%s(%sa + 2, %s);\n", dstwx, to, from);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error(to, 2, 1, 1, from, 1);
                                }
                                break;
@@ -3679,26 +3727,23 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                } else if (using_prefetch) {
                        switch (size) {
                        case sz_byte:
-                               insn_n_cycles += 4;
                                out("%s(%sa, %s);\n", dstbx, to, from);
-                               count_write++;
+                               count_writew++;
                                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();
                                out("%s(%sa, %s);\n", dstwx, to, from);
-                               count_write++;
+                               count_writew++;
                                check_bus_error(to, 0, 1, 1, from, 1);
                                break;
                        case sz_long:
-                               insn_n_cycles += 8;
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
                                        term();
                                if (store_dir) {
                                        out("%s(%sa + 2, %s);\n", dstwx, to, from);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error(to, 2, 1, 1, from, 1);
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
@@ -3709,18 +3754,18 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        }
                                        out("%s(%sa, %s >> 16); \n", dstwx, to, from);
                                        sprintf(tmp, "%s >> 16", from);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error(to, 0, 1, 1, tmp, 1);
                                } else {
                                        out("%s(%sa, %s >> 16);\n", dstwx, to, from);
                                        sprintf(tmp, "%s >> 16", from);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error(to, 0, 1, 1, tmp, 1);
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
                                        out("%s(%sa + 2, %s); \n", dstwx, to, from);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error(to, 2, 1, 1, from, 1);
                                }
                                break;
@@ -3730,25 +3775,26 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                } else {
                        switch (size) {
                        case sz_byte:
-                               insn_n_cycles += 4;
                                out("%s(%sa, %s);\n", dstbx, to, from);
-                               count_write++;
+                               count_writew++;
                                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();
                                out("%s(%sa, %s);\n", dstwx, to, from);
-                               count_write++;
+                               count_writew++;
                                check_bus_error(to, 0, 1, 1, from, 1);
                                break;
                        case sz_long:
-                               insn_n_cycles += 8;
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
                                        term();
+                               // ADDX.L/SUBX.L -(an),-(an) only
+                               if (store_dir > 1) {
+                                       insn_n_cycles += 4;
+                               }
                                out("%s(%sa, %s);\n", dstlx, to, from);
-                               count_write += 2;
+                               count_writel++;
                                check_bus_error(to, 0, 1, 2, from, 1);
                                break;
                        default:
@@ -4063,7 +4109,7 @@ static void movem_ex3(int write)
 }
 
 
-static void genmovemel (uae_u16 opcode)
+static void genmovemel(uae_u16 opcode)
 {
        char getcode[100];
        int size = table68k[opcode].size == sz_long ? 4 : 2;
@@ -4073,7 +4119,13 @@ static void genmovemel (uae_u16 opcode)
        } else {
                sprintf(getcode, "(uae_s32)(uae_s16)%s(srca)", srcwd);
        }
-       count_read += table68k[opcode].size == sz_long ? 2 : 1;
+       if (!using_simple_cycles && !do_always_dynamic_cycles) {
+               if (size == 4) {
+                       count_readl++;
+               } else {
+                       count_readw++;
+               }
+       }
        out("uae_u16 mask = %s;\n", gen_nextiword (0));
        out("uae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
        genamode(NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? -3 : -1, GF_MOVE);
@@ -4088,27 +4140,39 @@ static void genmovemel (uae_u16 opcode)
        } else {
                out("while (dmask) {\n");
                out("m68k_dreg(regs, movem_index1[dmask]) = %s;\n", getcode);
+               if (cpu_level <= 3) {
+                       addcycles000_nonce(cpu_level <= 1 ? size * 2 : 4);
+               }
                check_bus_error("src", 0, 0, table68k[opcode].size, NULL, 1);
                out("srca += %d;\n", size);
                out("dmask = movem_next[dmask];\n");
                out("}\n");
                out("while (amask) {\n");
                out("m68k_areg(regs, movem_index1[amask]) = %s;\n", getcode);
+               if (cpu_level <= 3) {
+                       addcycles000_nonce(cpu_level <= 1 ? size * 2 : 4);
+               }
                check_bus_error("src", 0, 0, table68k[opcode].size, NULL, 1);
                out("srca += %d;\n", size);
                out("amask = movem_next[amask];\n");
                out("}\n");
                if (table68k[opcode].dmode == Aipi) {
                        out("m68k_areg(regs, dstreg) = srca;\n");
-                       count_read++;
                }
+               if (cpu_level <= 3) {
+                       out("%s(srca);\n", srcw); // and final extra word fetch that goes nowhere..
+                       count_readw++;
+                       check_bus_error("src", 0, 0, 1, NULL, 1);
+               }
+               if (!next_level_040_to_030())
+                       next_level_020_to_010();
        }
        count_ncycles++;
        fill_prefetch_next_t();
        get_prefetch_020();
 }
 
-static void genmovemel_ce (uae_u16 opcode)
+static void genmovemel_ce(uae_u16 opcode)
 {
        int size = table68k[opcode].size == sz_long ? 4 : 2;
        out("uae_u16 mask = %s;\n", gen_nextiword (0));
@@ -4164,7 +4228,7 @@ static void genmovemel_ce (uae_u16 opcode)
                out("}\n");
        }
        out("%s(srca);\n", srcw); // and final extra word fetch that goes nowhere..
-       count_read++;
+       count_readw++;
        check_bus_error("src", 0, 0, 1, NULL, 1);
        if (table68k[opcode].dmode == Aipi)
                out("m68k_areg(regs, dstreg) = srca;\n");
@@ -4172,20 +4236,24 @@ static void genmovemel_ce (uae_u16 opcode)
        fill_prefetch_next_t();
 }
 
-static void genmovemle (uae_u16 opcode)
+static void genmovemle(uae_u16 opcode)
 {
        char putcode[100];
        int size = table68k[opcode].size == sz_long ? 4 : 2;
 
-       if (table68k[opcode].size == sz_long) {
+       if (size == 4) {
                sprintf(putcode, "%s(srca", dstld);
        } else {
                sprintf(putcode, "%s(srca", dstwd);
        }
-       count_write += table68k[opcode].size == sz_long ? 2 : 1;
-
+       if (!using_simple_cycles && !do_always_dynamic_cycles) {
+               if (size == 4)
+                       count_writel++;
+               else
+                       count_writew++;
+       }
        out("uae_u16 mask = %s;\n", gen_nextiword (0));
-       genamode(NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, GF_MOVE);
+       genamode(NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, GF_MOVE | GF_APDI);
        addcycles_ce020 (4 - 2);
        if (using_mmu >= 68030) {
                if (table68k[opcode].dmode == Apdi)
@@ -4205,16 +4273,23 @@ static void genmovemle (uae_u16 opcode)
                if (table68k[opcode].dmode == Apdi) {
                        out("uae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
                        movem_ex3(1);
-                       if (!using_mmu)
-                               out("int type = get_cpu_model() >= 68020;\n");
+                       if (!using_mmu) {
+                               out("int type = %d;\n", cpu_level > 1);
+                       }
                        out("while (amask) {\n");
                        out("srca -= %d;\n", size);
 
                        out("if (!type || movem_index2[amask] != dstreg) {\n");
                        out("%s, m68k_areg(regs, movem_index2[amask]));\n", putcode);
+                       if (cpu_level <= 3) {
+                               addcycles000_nonce(cpu_level <= 1 ? size * 2 : 4);
+                       }
                        check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_areg(regs, movem_index2[amask])", 1);
                        out("} else {\n");
                        out("%s, m68k_areg(regs, movem_index2[amask]) - %d);\n", putcode, size);
+                       if (cpu_level <= 3) {
+                               addcycles000_nonce(cpu_level <= 1 ? size * 2 : 4);
+                       }
                        if (size == 4) {
                                check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_areg(regs, movem_index2[amask]) - 4", 1);
                        } else {
@@ -4226,6 +4301,9 @@ static void genmovemle (uae_u16 opcode)
                        out("while (dmask) {\n");
                        out("srca -= %d;\n", size);
                        out("%s, m68k_dreg(regs, movem_index2[dmask]));\n", putcode);
+                       if (cpu_level <= 3) {
+                               addcycles000_nonce(cpu_level <= 1 ? size * 2 : 4);
+                       }
                        check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_dreg(regs, movem_index2[dmask])", 1);
                        out("dmask = movem_next[dmask];\n");
                        out("}\n");
@@ -4234,17 +4312,25 @@ static void genmovemle (uae_u16 opcode)
                        out("uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
                        out("while (dmask) {\n");
                        out("%s, m68k_dreg(regs, movem_index1[dmask]));\n", putcode);
+                       if (cpu_level <= 3) {
+                               addcycles000_nonce(cpu_level <= 1 ? size * 2 : 4);
+                       }
                        check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_dreg(regs, movem_index1[dmask])", 1);
                        out("srca += %d;\n", size);
                        out("dmask = movem_next[dmask];\n");
                        out("}\n");
                        out("while (amask) {\n");
                        out("%s, m68k_areg(regs, movem_index1[amask]));\n", putcode);
+                       if (cpu_level <= 3) {
+                               addcycles000_nonce(cpu_level <= 1 ? size * 2 : 4);
+                       }
                        check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_areg(regs, movem_index1[amask])", 1);
                        out("srca += %d;\n", size);
                        out("amask = movem_next[amask];\n");
                        out("}\n");
                }
+               if (!next_level_040_to_030())
+                       next_level_020_to_010();
        }
        count_ncycles++;
        fill_prefetch_next_t();
@@ -4396,8 +4482,12 @@ static void shift_ce (amodes dmode, int size)
                        addcycles000_3();
                        out("}\n");
                }
-               addcycles000_nonces("2 * ccnt");
+               next_level_020_to_010();
+               if ((using_simple_cycles || do_always_dynamic_cycles) && cpu_level <= 1) {
+                       addcycles000_nonces("2 * ccnt");
+               }
                count_cycles += c;
+               insn_n_cycles += c;
                count_ncycles++;
        }
 }
@@ -4415,7 +4505,8 @@ static void bsetcycles (struct instr *curi)
                                if (using_ce) {
                                        out("if (src > 15) %s(2);\n", do_cycles);
                                }
-                               if (using_simple_cycles) {
+                               next_level_020_to_010();
+                               if ((using_simple_cycles || do_always_dynamic_cycles) && cpu_level <= 1) {
                                        out("if (src > 15) {\n");
                                        out("count_cycles += % d * CYCLE_UNIT / 2;\n", 2);
                                        out("}\n");
@@ -4434,8 +4525,7 @@ static int islongimm (struct instr *curi)
 
 static void resetvars (void)
 {
-       insn_n_cycles = using_prefetch ? 0 : 4;
-       insn_n_cycles020 = 0;
+       insn_n_cycles = 0;
        genamode_cnt = 0;
        genamode8r_offset[0] = genamode8r_offset[1] = 0;
        m68k_pc_total = 0;
@@ -5658,23 +5748,23 @@ static void gen_opcode (unsigned int opcode)
                check_prefetch_buserror(m68k_pc_offset);
                if (curi->size == sz_word) {
                        out("%s(mempa, src >> 8);\n", dstb);
-                       count_write++;
+                       count_writew++;
                        check_bus_error("memp", 0, 1, 0, "src >> 8", 1 | 0x10000);
                        out("%s(mempa + 2, src); \n", dstb);
-                       count_write++;
+                       count_writew++;
                        check_bus_error("memp", 2, 1, 0, "src", 1);
                } else {
                        out("%s(mempa, src >> 24);\n", dstb);
-                       count_write++;
+                       count_writew++;
                        check_bus_error("memp", 0, 1, 0, "src >> 24", 1 | 0x10000);
                        out("%s(mempa + 2, src >> 16);\n", dstb);
-                       count_write++;
+                       count_writew++;
                        check_bus_error("memp", 2, 1, 0, "src >> 16", 1);
                        out("%s(mempa + 4, src >> 8);\n", dstb);
-                       count_write++;
+                       count_writew++;
                        check_bus_error("memp", 4, 1, 0, "src >> 8", 1 | 0x10000);
                        out("%s(mempa + 6, src); \n", dstb);
-                       count_write++;
+                       count_writew++;
                        check_bus_error("memp", 6, 1, 0, "src", 1);
                }
                fill_prefetch_next_t();
@@ -5686,17 +5776,17 @@ static void gen_opcode (unsigned int opcode)
                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);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("memp", 0, 0, 0, NULL, 1 | 0x10000);
                        out("val |= (%s(mempa + 2) & 0xff);\n", srcb);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("memp", 2, 0, 0, NULL, 1);
                } else {
                        out("uae_u32 val  = (%s(mempa) & 0xff) << 24;\n", srcb);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("memp", 0, 0, 0, NULL, 1 | 0x10000);
                        out("val |= (%s(mempa + 2) & 0xff) << 16;\n", srcb);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("memp", 2, 0, 0, NULL, 1);
 
                        // upper word gets updated after two bytes (makes only difference if bus error is possible)
@@ -5705,10 +5795,10 @@ static void gen_opcode (unsigned int opcode)
                        }
 
                        out("val |= (%s(mempa + 4) & 0xff) << 8;\n", srcb);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("memp", 4, 0, 0, NULL, 1 | 0x10000);
                        out("val |= (%s(mempa + 6) & 0xff);\n", srcb);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("memp", 6, 0, 0, NULL, 1);
                }
                genastore("val", curi->dmode, "dstreg", curi->size, "dst");
@@ -5961,7 +6051,7 @@ static void gen_opcode (unsigned int opcode)
                        // 68000: read first and ignore result
                        if (cpu_level == 0 && curi->size == sz_word) {
                                out("%s(srca);\n", srcw);
-                               count_write++;
+                               count_writew++;
                                check_bus_error("src", 0, 0, 1, NULL, 1);
                        }
                        fill_prefetch_next_after(1, NULL);
@@ -6041,17 +6131,17 @@ static void gen_opcode (unsigned int opcode)
        case i_MVMEL:
                // confirmed
                if (using_ce || using_prefetch)
-                       genmovemel_ce (opcode);
+                       genmovemel_ce(opcode);
                else
-                       genmovemel (opcode);
+                       genmovemel(opcode);
                tail_ce020_done = true;
                break;
        case i_MVMLE:
                // confirmed
                if (using_ce || using_prefetch)
-                       genmovemle_ce (opcode);
+                       genmovemle_ce(opcode);
                else
-                       genmovemle (opcode);
+                       genmovemle(opcode);
                tail_ce020_done = true;
                break;
        case i_TRAP:
@@ -6168,16 +6258,16 @@ static void gen_opcode (unsigned int opcode)
                        out("uaecptr oldpc = %s;\n", getpc);
                        out("uaecptr a = m68k_areg(regs, 7);\n");
                        out("uae_u16 sr = %s(a);\n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("", 0, 0, 1, NULL, 1);
 
                        out("m68k_areg(regs, 7) += 6;\n");
 
                        out("uae_u32 pc = %s(a + 2) << 16;\n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("", 2, 0, 1, NULL, 1);
                        out("pc |= %s(a + 2 + 2); \n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("", 4, 0, 1, NULL, 1);
 
                        out("uae_u16 oldt1 = regs.t1;\n");
@@ -6188,7 +6278,9 @@ static void gen_opcode (unsigned int opcode)
                        write_return_cycles(0);
                        out("}\n");
                        setpc ("pc");
-                       out("opcode |= 0x20000;\n");
+                       if (using_prefetch) {
+                               out("opcode |= 0x20000;\n");
+                       }
                        if (using_debugmem) {
                                out("branch_stack_pop_rte(oldpc);\n");
                        }
@@ -6200,15 +6292,15 @@ static void gen_opcode (unsigned int opcode)
                        out("uae_u32 newpc;\n");
                        out("uaecptr a = m68k_areg(regs, 7);\n");
                        out("uae_u16 sr = %s(a);\n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("", 0, 0, 1, NULL, 1);
 
                        out("uae_u16 format = %s(a + 2 + 4);\n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("", 6, 0, 1, NULL, 1);
 
                        out("uae_u32 pc = %s(a + 2) << 16;\n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("", 2, 0, 1, NULL, 1);
 
                        out("int frame = format >> 12;\n");
@@ -6226,7 +6318,7 @@ static void gen_opcode (unsigned int opcode)
                        out("}\n");
 
                        out("pc |= %s(a + 2 + 2); \n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("", 4, 0, 1, NULL, 1);
                        out("regs.sr = sr;\n");
                        makefromsr();
@@ -6247,11 +6339,11 @@ static void gen_opcode (unsigned int opcode)
                        out("for (;;) {\n");
                        out("uaecptr a = m68k_areg(regs, 7);\n");
                        out("uae_u16 sr = %s(a);\n", srcw);
-                       count_read++;
+                       count_readw++;
                        out("uae_u32 pc = %s(a + 2);\n", srcl);
-                       count_read += 2;
+                       count_readl++;
                        out("uae_u16 format = %s(a + 2 + 4);\n", srcw);
-                       count_read++;
+                       count_readw++;
                        out("int frame = format >> 12;\n");
                        out("int offset = 8;\n");
                        out("newsr = sr; newpc = pc;\n");
@@ -6420,10 +6512,8 @@ static void gen_opcode (unsigned int opcode)
                        genastore("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
                        out("m68k_areg(regs, 7) += offs;\n");
                        fill_prefetch_next_t();
-                       if (cpu_level >= 5) {
-                               if (next_cpu_level < 5)
-                                       next_cpu_level = 5 - 1;
-                       }
+                       if (!next_level_060_to_040())
+                               next_level_020_to_010();
                }
                break;
        case i_UNLK:
@@ -6452,34 +6542,34 @@ static void gen_opcode (unsigned int opcode)
                }
                if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce && !using_test) {
                        out("m68k_do_rtsi_jit();\n");
-                       count_read += 2;
+                       count_readl++;
                } else if (using_mmu) {
                        out("m68k_do_rts_mmu%s();\n", mmu_postfix);
-                       count_read += 2;
+                       count_readl++;
                } else if (using_ce020 == 1) {
                        add_head_cycs (1);
                        out("m68k_do_rts_ce020();\n");
-                       count_read += 2;
+                       count_readl++;
                } else if (using_ce020 == 2) {
                        add_head_cycs (1);
                        out("m68k_do_rts_ce030();\n");
-                       count_read += 2;
+                       count_readl++;
                } else if (using_ce || using_prefetch || (using_test && cpu_level <= 1)) {
                        out("uaecptr newpc, dsta = m68k_areg(regs, 7);\n");
                        out("newpc = %s(dsta) << 16;\n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("dst", 0, 0, 1, NULL, 1);
                        out("newpc |= %s(dsta + 2);\n", srcw);
-                       count_read++;
+                       count_readw++;
                        check_bus_error("dst", 2, 0, 1, NULL, 1);
                        out("m68k_areg(regs, 7) += 4;\n");
                        setpc("newpc");
                } else if (using_prefetch_020 || (using_test && cpu_level >= 2)) {
                        out("m68k_do_rtsi();\n");
-                       count_read += 2;
+                       count_readl++;
                } else {
                        out("m68k_do_rts();\n");
-                       count_read += 2;
+                       count_readl++;
                }
                if (using_debugmem) {
                        out("if (debugmem_trace) {\n");
@@ -6654,17 +6744,17 @@ static void gen_opcode (unsigned int opcode)
                                if (using_ce || using_prefetch) {
                                        out("uaecptr dsta = m68k_areg(regs, 7);\n");
                                        out("%s(dsta, nextpc >> 16);\n", dstw);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error("dst", 0, 1, 1, "nextpc >> 16", 1);
                                        out("%s(dsta + 2, nextpc);\n", dstw);
-                                       count_write++;
+                                       count_writew++;
                                        check_bus_error("dst", 2, 1, 1, "nextpc", 1);
                                } else {
                                        if (cpu_level < 4)
                                                out("%s(m68k_areg(regs, 7), nextpc);\n", dstl);
                                        else
                                                out("%s(m68k_areg(regs, 7) - 4, nextpc);\n", dstl);
-                                       count_write += 2;
+                                       count_writel++;
                                }
                                if (cpu_level >= 4)
                                        out("m68k_areg(regs, 7) -= 4;\n");
@@ -6682,11 +6772,10 @@ static void gen_opcode (unsigned int opcode)
                                if (sp < 0 && cpu_level == 0)
                                        out("if(regs.t1) opcode |= 0x10000;\n");
                                out("%s(%d);\n", prefetch_word, 2);
-                               count_read++;
+                               count_readw++;
                                check_prefetch_bus_error(-2, sp);
                                did_prefetch = 1;
                                ir2irc = 0;
-                               insn_n_cycles += 4;
                        } else {
                                fill_prefetch_next_empty();
                        }
@@ -6725,7 +6814,7 @@ static void gen_opcode (unsigned int opcode)
                clear_m68k_offset();
                if (using_prefetch || using_ce) {
                        out("%s(%d);\n", prefetch_word, 0);
-                       count_read++;
+                       count_readw++;
                        check_prefetch_bus_error(-1, 0);
                        irc2ir();
                        out("%s(%d);\n", prefetch_word, 2);
@@ -6733,11 +6822,10 @@ static void gen_opcode (unsigned int opcode)
                        copy_opcode();
                        if (sp < 0 && cpu_level == 0)
                                out("if(regs.t1) opcode |= 0x10000;\n");
-                       count_read++;
+                       count_readw++;
                        check_prefetch_bus_error(-2, sp);
                        did_prefetch = 1;
                        ir2irc = 0;
-                       insn_n_cycles += 2 * 4;
                } else {
                        fill_prefetch_full(0);
                }
@@ -6793,27 +6881,34 @@ static void gen_opcode (unsigned int opcode)
                        out("}\n");
                }
                if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce && !using_test) {
-                       out("m68k_do_bsri_jit (nextpc, s);\n");
+                       out("m68k_do_bsri_jit(nextpc, s);\n");
+                       count_writel++;
                } else if (using_mmu) {
                        out("m68k_do_bsr_mmu%s(nextpc, s);\n", mmu_postfix);
+                       count_writel++;
                } else if (using_ce020 == 1) {
                        out("m68k_do_bsr_ce020(nextpc, s);\n");
+                       count_writel++;
                } else if (using_ce020 == 2) {
                        out("m68k_do_bsr_ce030(nextpc, s);\n");
+                       count_writel++;
                } else if (using_ce || using_prefetch || (using_test && cpu_level <= 1)) {
                        out("m68k_areg(regs, 7) -= 4;\n");
                        out("uaecptr dsta = m68k_areg(regs, 7);\n");
                        out("%s(dsta, nextpc >> 16);\n", dstw);
                        check_bus_error("dst", 0, 1, 1, "nextpc >> 16", 1);
+                       count_writew++;
                        out("%s(dsta + 2, nextpc);\n", dstw);
                        check_bus_error("dst", 2, 1, 1, "nextpc", 1);
+                       count_writew++;
                        incpc("s");
                } else if (using_prefetch_020 || (using_test && cpu_level >= 2)) {
                        out("m68k_do_bsri(nextpc, s);\n");
+                       count_writel++;
                } else {
                        out("m68k_do_bsr(nextpc, s);\n");
+                       count_writel++;
                }
-               count_write += 2;
                if (using_exception_3 && cpu_level == 0) {
                        out("if (%s & 1) {\n", getpc);
                        out("exception3_read_prefetch(opcode, %s);\n", getpc);
@@ -6911,8 +7006,8 @@ static void gen_opcode (unsigned int opcode)
                insn_n_cycles = curi->size == sz_byte ? 8 : 12;
                branch_inst = 1;
 bccl_not68020:
-               next_level_040_to_030();
-               next_level_000();
+               if (!next_level_040_to_030())
+                       next_level_020_to_010();
                break;
        case i_LEA:
                if (curi->smode == Ad8r || curi->smode == PC8r)
@@ -6962,7 +7057,7 @@ bccl_not68020:
                genamodedual(curi,
                        curi->smode, "srcreg", curi->size, "src", 1, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0),
                        curi->dmode, "dstreg", curi->size, "offs", 1, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0));
-               if (cpu_level == 1) {
+               if (cpu_level == 1 && using_prefetch) {
                        out("int was_loop_mode = regs.loop_mode;\n");
                        out("regs.loop_mode = 0;\n");
                }
@@ -6983,7 +7078,7 @@ bccl_not68020:
                }
                if (using_exception_3 && cpu_level < 4) {
                        out("if (offs & 1) {\n");
-                       if (cpu_level == 1) {
+                       if (cpu_level == 1 && using_prefetch) {
                                out("%s(%d);\n", prefetch_word, -1);
                        }
                        out("exception3_read_prefetch(opcode, %s);\n", getpc);
@@ -6992,7 +7087,7 @@ bccl_not68020:
                        
                }
                // 68010 loop mode handling
-               if (cpu_level == 1) {
+               if (cpu_level == 1 && using_prefetch) {
                        out("if(offs == -4 && !regs.t1 && loop_mode_table[regs.ird]) {\n");
                        // first loop takes as many cycles as normal DBcc branch
                        // perhaps it also does actual prefetches??
@@ -7075,14 +7170,13 @@ bccl_not68020:
                        check_prefetch_bus_error(-2, -1);
                        did_prefetch = 1;
                        ir2irc = 0;
-                       count_read++;
-                       insn_n_cycles += 4;
+                       count_readw++;
                }
 
                fill_prefetch_full_020();
                returncycles (10);
                out("}\n");
-               if (cpu_level == 1) {
+               if (cpu_level == 1 && using_prefetch) {
                        out("if (!src) {\n");
                        addcycles000_onlyce(2);
                        addcycles000_nonce(2);
@@ -7090,7 +7184,7 @@ bccl_not68020:
                }
                add_head_cycs (10);
                addcycles000_nonce(2 + 2);
-               if (cpu_level == 0) {
+               if (cpu_level == 0 || (cpu_level == 1 && !using_prefetch)) {
                        out("} else {\n");
                        addcycles000_onlyce(2);
                        addcycles000_nonce(2);
@@ -7101,9 +7195,10 @@ bccl_not68020:
                clear_m68k_offset();
                get_prefetch_020_continue();
                fill_prefetch_full_000_special("if (!cctrue(%d)) {\nm68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src - 1)) & 0xffff);\n}\n", curi->cc);
-               insn_n_cycles = 12;
+               insn_n_cycles = 8;
                branch_inst = 1;
-               next_level_040_to_030();
+               if (!next_level_040_to_030())
+                       next_level_020_to_010();
                break;
        case i_Scc:
                genamode(curi, curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, cpu_level == 1 ? GF_NOFETCH : 0);
@@ -7146,12 +7241,14 @@ bccl_not68020:
                out("}\n");
                pop_ins_cnt();
                out("uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
-               out("uae_u32 rem = (uae_u32)dst %%%% (uae_u32)(uae_u16)src;\n");
+               out("uae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
                if (using_ce) {
                        out("int cycles = getDivu68kCycles((uae_u32)dst, (uae_u16)src);\n");
                        addcycles000_3();
                }
-               addcycles000_nonces("getDivu68kCycles((uae_u32)dst, (uae_u16)src)");
+               if (cpu_level <= 1) {
+                       addcycles000_nonces("getDivu68kCycles((uae_u32)dst, (uae_u16)src)");
+               }
                out("if (newv > 0xffff) {\n");
                out("setdivuflags((uae_u32)dst, (uae_u16)src);\n");
                out("} else {\n");
@@ -7162,9 +7259,12 @@ bccl_not68020:
                fill_prefetch_next_t();
                sync_m68k_pc();
                count_ncycles++;
-               insn_n_cycles += 136 - (136 - 76) / 2; /* average */
+               if (!do_always_dynamic_cycles) {
+                       insn_n_cycles += 136 - (136 - 76) / 3; /* average */
+               }
                tail_ce020_done = false;
                returntail(false);
+               next_level_020_to_010();
                break;
        case i_DIVS:
                tail_ce020_done = true;
@@ -7184,12 +7284,14 @@ bccl_not68020:
                        out("int cycles = getDivs68kCycles((uae_s32)dst, (uae_s16)src);\n");
                        addcycles000_3();
                }
-               addcycles000_nonces("getDivs68kCycles((uae_s32)dst, (uae_s16)src)");
+               if (cpu_level <= 1) {
+                       addcycles000_nonces("getDivs68kCycles((uae_s32)dst, (uae_s16)src)");
+               }
                out("if (dst == 0x80000000 && src == -1) {\n");
                out("setdivsflags((uae_s32)dst, (uae_s16)src);\n");
                out("} else {\n");
                out("uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
-               out("uae_u16 rem = (uae_s32)dst %%%% (uae_s32)(uae_s16)src;\n");
+               out("uae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
                out("if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) {\n");
                out("setdivsflags((uae_s32)dst, (uae_s16)src);\n");
                out("} else {\n");
@@ -7202,9 +7304,12 @@ bccl_not68020:
                fill_prefetch_next_t();
                sync_m68k_pc();
                count_ncycles++;
-               insn_n_cycles += 156 - (156 - 120) / 2; /* average */
+               if (!do_always_dynamic_cycles) {
+                       insn_n_cycles += 156 - (156 - 120) / 3; /* average */
+               }
                tail_ce020_done = false;
                returntail(false);
+               next_level_020_to_010();
                break;
        case i_MULU:
                genamodedual(curi,
@@ -7220,11 +7325,16 @@ bccl_not68020:
                        out("int cycles = getMulu68kCycles(src);\n");
                        addcycles000_3();
                }
-               addcycles000_nonces("getMulu68kCycles(src)");
+               if (cpu_level <= 1) {
+                       addcycles000_nonces("getMulu68kCycles(src)");
+               }
                genastore("newv", curi->dmode, "dstreg", sz_long, "dst");
                sync_m68k_pc();
                count_ncycles++;
-               insn_n_cycles += (70 - 38) / 2 + 38; /* average */
+               if (!do_always_dynamic_cycles) {
+                       insn_n_cycles += (70 - 38) / 3 + 38; /* average */
+               }
+               next_level_020_to_010();
                break;
        case i_MULS:
                genamodedual(curi,
@@ -7240,10 +7350,15 @@ bccl_not68020:
                        out("int cycles = getMuls68kCycles(src);\n");
                        addcycles000_3();
                }
-               addcycles000_nonces("getMuls68kCycles(src)");
+               if (cpu_level <= 1) {
+                       addcycles000_nonces("getMuls68kCycles(src)");
+               }
                genastore("newv", curi->dmode, "dstreg", sz_long, "dst");
                count_ncycles++;
-               insn_n_cycles += (70 - 38) / 2 + 38; /* average */
+               if (!do_always_dynamic_cycles) {
+                       insn_n_cycles += (70 - 38) / 3 + 38; /* average */
+               }
+               next_level_020_to_010();
                break;
        case i_CHK:
                genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
@@ -7472,7 +7587,7 @@ bccl_not68020:
                out("int ccnt = cnt & 63;\n");
                out("cnt &= 63;\n");
                if (source_is_imm1_8 (curi))
-                       out("{");
+                       out("{\n");
                else
                        out("if (cnt > 0) {\n");
                out("uae_u32 loval;\n");
@@ -7506,9 +7621,9 @@ bccl_not68020:
                out("int ccnt = cnt & 63;\n");
                out("cnt &= 63;\n");
                if (source_is_imm1_8 (curi))
-                       out("{");
+                       out("{\n");
                else
-                       out("if (cnt > 0) {");
+                       out("if (cnt > 0) {\n");
                out("uae_u32 hival;\n");
                out("cnt &= %d;\n", bit_size (curi->size) - 1);
                out("hival = val << (%d - cnt);\n", bit_size (curi->size));
@@ -7540,7 +7655,7 @@ bccl_not68020:
                out("int ccnt = cnt & 63;\n");
                out("cnt &= 63;\n");
                if (source_is_imm1_8 (curi))
-                       out("{");
+                       out("{\n");
                else {
                        force_range_for_rox ("cnt", curi->size);
                        out("if (cnt > 0) {\n");
@@ -7552,7 +7667,8 @@ bccl_not68020:
                out("val = (((val << 1) | GET_XFLG()) << cnt) | (loval >> 1);\n");
                out("SET_XFLG(carry);\n");
                out("val &= %s;\n", bit_mask (curi->size));
-               out("} }\n");
+               out("}\n");
+               out("}\n");
                out("SET_CFLG(GET_XFLG());\n");
                genflags (flag_logical_noclobber, curi->size, "val", "", "");
                shift_ce (curi->dmode, curi->size);
@@ -7577,7 +7693,7 @@ bccl_not68020:
                out("int ccnt = cnt & 63;\n");
                out("cnt &= 63;\n");
                if (source_is_imm1_8 (curi))
-                       out("{");
+                       out("{\n");
                else {
                        force_range_for_rox ("cnt", curi->size);
                        out("if (cnt > 0) {\n");
@@ -7592,7 +7708,8 @@ bccl_not68020:
                out("val |= hival;\n");
                out("SET_XFLG(carry);\n");
                out("val &= %s;\n", bit_mask (curi->size));
-               out("} }\n");
+               out("}\n");
+               out("}\n");
                out("SET_CFLG(GET_XFLG());\n");
                genflags (flag_logical_noclobber, curi->size, "val", "", "");
                shift_ce (curi->dmode, curi->size);
@@ -8371,7 +8488,7 @@ end:
                int v = curi->clocks;
                if (v < 4)
                        v = 4;
-               count_cycles = insn_n_cycles = v;
+               count_cycles = v;
        }
 }
 
@@ -8582,7 +8699,7 @@ static void generate_one_opcode (int rp, const char *extra)
        if (i68000)
                out("#ifndef CPUEMU_68000_ONLY\n");
        out("%s REGPARAM2 CPUFUNC(op_%04x_%d%s)(uae_u32 opcode)\n{\n", (using_ce || using_ce020) ? "void" : "uae_u32", opcode, postfix, extra);
-       if (using_simple_cycles)
+       if (using_simple_cycles || do_always_dynamic_cycles)
                out("int count_cycles = 0;\n");
 
        switch (table68k[opcode].stype) {
@@ -8646,7 +8763,8 @@ static void generate_one_opcode (int rp, const char *extra)
                                out("uae_u32 dstreg = opcode & %d;\n", dmsk);
                }
        }
-       count_read = count_write = count_ncycles = count_cycles = 0;
+       count_readw = count_readl = count_writew = count_writel = count_ncycles = count_cycles = 0;
+       count_readp = 0;
        count_cycles_ce020 = 0;
        count_read_ea = count_write_ea = count_cycles_ea = 0;
        gen_opcode (opcode);
@@ -8973,8 +9091,10 @@ static void generate_cpu (int id, int mode)
                        for (rp = 0; rp < nr_cpuop_funcs; rp++)
                                opcode_next_clev[rp] = cpu_level;
                }
-        }
+       }
  
+       do_always_dynamic_cycles = !using_simple_cycles && !using_prefetch && !using_prefetch_020 && using_always_dynamic_cycles;
+
        if (!using_indirect)
                using_indirect = using_ce || using_ce020 || using_prefetch_020 || id >= 50;
 
index ca5823eb7db3af0707e6b627dbd703381ed8e578..9875066a6ce166a3a3e6e0ae0d5dacd6970c187d 100644 (file)
@@ -185,6 +185,7 @@ struct regstruct
        uae_u32 chipset_latch_write;
        uae_u16 db, write_buffer, read_buffer;
        int loop_mode;
+       int instruction_cnt;
 
        uaecptr usp, isp, msp;
        uae_u16 sr;
index 5142c3449302d7985748e192f2a727e99e10ecff..3e3ad1b4f49a445b5bdf3439c8c4eb72f71f6630 100644 (file)
@@ -2812,8 +2812,8 @@ static void add_approximate_exception_cycles(int nr)
                        /* Interrupts */
                        cycles = 44;
                } else if (nr >= 32 && nr <= 47) {
-                       /* Trap (total is 34, but cpuemux.c already adds 4) */
-                       cycles = 34 - 4;
+                       /* Trap */
+                       cycles = 34;
                } else {
                        switch (nr)
                        {
@@ -2838,7 +2838,7 @@ static void add_approximate_exception_cycles(int nr)
                        cycles = 48;
                } else if (nr >= 32 && nr <= 47) {
                        /* Trap */
-                       cycles = 38 - 4;
+                       cycles = 38;
                } else {
                        switch (nr)
                        {
@@ -4517,10 +4517,11 @@ static void m68k_run_1 (void)
                                }
                                do_cycles (cpu_cycles);
                                r->instruction_pc = m68k_getpc ();
-                               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
+                               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode) & 0xffff;
                                if (!regs.loop_mode)
                                        regs.ird = regs.opcode;
                                cpu_cycles = adjust_cycles (cpu_cycles);
+                               regs.instruction_cnt++;
                                if (r->spcflags) {
                                        if (do_specialties (cpu_cycles))
                                                exit = true;
@@ -4636,6 +4637,7 @@ static void m68k_run_1_ce (void)
                                (*cpufunctbl[r->opcode])(r->opcode);
                                if (!regs.loop_mode)
                                        regs.ird = regs.opcode;
+                               regs.instruction_cnt++;
                                wait_memory_cycles();
                                if (cpu_tracer) {
                                        cputrace.state = 0;
@@ -5003,7 +5005,7 @@ void exec_nostats (void)
                } else {
                        r->opcode = x_get_iword(0);
                }
-               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
+               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode) >> 16;
                cpu_cycles = adjust_cycles (cpu_cycles);
 
                if (!currprefs.cpu_thread) {
@@ -5046,7 +5048,7 @@ void execute_normal (void)
                special_mem = DISTRUST_CONSISTENT_MEM;
                pc_hist[blocklen].location = (uae_u16*)r->pc_p;
 
-               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
+               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode) >> 16;
                cpu_cycles = adjust_cycles(cpu_cycles);
                if (!currprefs.cpu_thread) {
                        do_cycles (cpu_cycles);
@@ -5240,9 +5242,10 @@ static void m68k_run_mmu060 (void)
                                mmu060_state = 1;
 
                                count_instr (regs.opcode);
-                               cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
+                               cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode) >> 16;
 
                                cpu_cycles = adjust_cycles (cpu_cycles);
+                               regs.instruction_cnt++;
 
                                if (regs.spcflags) {
                                        if (do_specialties (cpu_cycles))
@@ -5288,8 +5291,9 @@ static void m68k_run_mmu040 (void)
                                mmu_opcode = -1;
                                mmu_opcode = regs.opcode = x_prefetch (0);
                                count_instr (regs.opcode);
-                               cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
+                               cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode) >> 16;
                                cpu_cycles = adjust_cycles (cpu_cycles);
+                               regs.instruction_cnt++;
 
                                if (regs.spcflags) {
                                        if (do_specialties (cpu_cycles))
@@ -5379,7 +5383,7 @@ insretry:
                                                count_instr (regs.opcode);
                                                do_cycles (cpu_cycles);
 
-                                               cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
+                                               cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode) >> 16;
 
                                        } else {
                                                
@@ -5404,6 +5408,7 @@ insretry:
                                if (!currprefs.cpu_cycle_exact) {
 
                                        cpu_cycles = adjust_cycles (cpu_cycles);
+                                       regs.instruction_cnt++;
                                        if (regs.spcflags) {
                                                if (do_specialties (cpu_cycles))
                                                        return;
@@ -5411,6 +5416,7 @@ insretry:
 
                                } else {
 
+                                       regs.instruction_cnt++;
                                        if (regs.spcflags || time_for_interrupt ()) {
                                                if (do_specialties (0))
                                                        return;
@@ -5480,6 +5486,7 @@ static void m68k_run_3ce (void)
                                                exit = true;
                                }
 
+                               regs.instruction_cnt++;
                                // workaround for situation when all accesses are cached
                                extracycles++;
                                if (extracycles >= 8) {
@@ -5522,6 +5529,7 @@ static void m68k_run_3p(void)
 
                                cpu_cycles = 1 * CYCLE_UNIT;
                                cycles = adjust_cycles(cpu_cycles);
+                               regs.instruction_cnt++;
                                do_cycles(cycles);
 
                                if (r->spcflags) {
@@ -5660,6 +5668,7 @@ static void m68k_run_2ce (void)
                                (*cpufunctbl[r->opcode])(r->opcode);
                
                                wait_memory_cycles();
+                               regs.instruction_cnt++;
 
                cont:
                                if (r->spcflags || time_for_interrupt ()) {
@@ -5783,9 +5792,6 @@ static void m68k_run_2p (void)
                                        debug_trainer_match();
                                }
 
-                               if (cpu_cycles > 0)
-                                       x_do_cycles(cpu_cycles);
-
                                if (currprefs.cpu_memory_cycle_exact) {
 
                                        (*cpufunctbl[r->opcode])(r->opcode);
@@ -5795,13 +5801,19 @@ static void m68k_run_2p (void)
                                        cpu_cycles -= CYCLE_UNIT;
                                        if (cpu_cycles <= 0)
                                                cpu_cycles = cpucycleunit;
+                                       regs.instruction_cnt++;
 
                                } else {
 
-                                       cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
+                                       cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode) >> 16;
                                        cpu_cycles = adjust_cycles (cpu_cycles);
+                                       regs.instruction_cnt++;
 
                                }
+
+                               if (cpu_cycles > 0)
+                                       x_do_cycles(cpu_cycles);
+
 cont:
                                if (r->spcflags) {
                                        if (do_specialties (cpu_cycles))
@@ -5862,7 +5874,43 @@ static void *cpu_thread_run_2(void *v)
 #endif
 
 /* Same thing, but don't use prefetch to get opcode.  */
-static void m68k_run_2 (void)
+static void m68k_run_2_000(void)
+{
+       struct regstruct *r = &regs;
+       bool exit = false;
+
+       while (!exit) {
+               TRY(prb) {
+                       while (!exit) {
+                               r->instruction_pc = m68k_getpc ();
+
+                               r->opcode = x_get_iword(0);
+                               count_instr (r->opcode);
+
+                               if (debug_opcode_watch) {
+                                       debug_trainer_match();
+                               }
+
+                               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode) & 0xffff;
+                               cpu_cycles = adjust_cycles (cpu_cycles);
+                               do_cycles(cpu_cycles);
+
+                               if (r->spcflags) {
+                                       if (do_specialties (cpu_cycles))
+                                               exit = true;
+                               }
+                       }
+               } CATCH(prb) {
+                       bus_error();
+                       if (r->spcflags) {
+                               if (do_specialties(cpu_cycles))
+                                       exit = true;
+                       }
+               } ENDTRY
+       }
+}
+
+static void m68k_run_2_020(void)
 {
 #ifdef WITH_THREADED_CPU
        if (currprefs.cpu_thread) {
@@ -5877,21 +5925,21 @@ static void m68k_run_2 (void)
        while (!exit) {
                TRY(prb) {
                        while (!exit) {
-                               r->instruction_pc = m68k_getpc ();
+                               r->instruction_pc = m68k_getpc();
 
                                r->opcode = x_get_iword(0);
-                               count_instr (r->opcode);
+                               count_instr(r->opcode);
 
                                if (debug_opcode_watch) {
                                        debug_trainer_match();
                                }
-                               do_cycles (cpu_cycles);
 
-                               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
-                               cpu_cycles = adjust_cycles (cpu_cycles);
+                               cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode) >> 16;
+                               cpu_cycles = adjust_cycles(cpu_cycles);
+                               do_cycles(cpu_cycles);
 
                                if (r->spcflags) {
-                                       if (do_specialties (cpu_cycles))
+                                       if (do_specialties(cpu_cycles))
                                                exit = true;
                                }
                        }
@@ -5905,6 +5953,7 @@ static void m68k_run_2 (void)
        }
 }
 
+
 /* fake MMU 68k  */
 #if 0
 static void m68k_run_mmu (void)
@@ -6146,7 +6195,7 @@ void m68k_go (int may_quit)
                                currprefs.cpu_model == 68030 && currprefs.cpu_compatible ? m68k_run_2p :
                                currprefs.cpu_model >= 68040 && currprefs.cpu_compatible ? m68k_run_3p :
 
-                               m68k_run_2;
+                               currprefs.cpu_model < 68020 ? m68k_run_2_000 : m68k_run_2_020;
 #if 0
                }
 #endif