]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68010 loop mode emulation.
authorToni Wilen <twilen@winuae.net>
Tue, 31 Dec 2019 11:23:47 +0000 (13:23 +0200)
committerToni Wilen <twilen@winuae.net>
Tue, 31 Dec 2019 11:23:47 +0000 (13:23 +0200)
gencpu.cpp
include/newcpu.h
include/readcpu.h
newcpu.cpp
readcpu.cpp

index d0583ba84ccd35b78d07e157a688f321348addce..ef2807bd8619d070343d2fcdb732e5a00a1eeb2e 100644 (file)
@@ -102,6 +102,7 @@ static bool genastore_done;
 static char rmw_varname[100];
 static struct instr *g_instr;
 static char g_srcname[100];
+static int loopmode;
 
 #define GENA_GETV_NO_FETCH     0
 #define GENA_GETV_FETCH                1
@@ -1041,9 +1042,26 @@ static void dummy_prefetch (void)
        check_prefetch_bus_error(o, 0);
 }
 
+static void loopmode_begin(void)
+{
+       if (loopmode) {
+               printf("\tif(!regs.loop_mode) {\n");
+               printf("\t\tregs.ird = opcode;\n");
+       }
+}
+static void loopmode_end(void)
+{
+       if (loopmode) {
+               printf("\t} else {\n");
+               addcycles000(2);
+               printf("\t}\n");
+       }
+}
+
 static void fill_prefetch_next_noopcodecopy(const char *format, ...)
 {
        if (using_prefetch) {
+               loopmode_begin();
                irc2ir();
                if (using_bus_error) {
                        bus_error_code[0] = 0;
@@ -1059,29 +1077,34 @@ static void fill_prefetch_next_noopcodecopy(const char *format, ...)
                if (using_bus_error) {
                        copy_opcode();
                }
+               loopmode_end();
        }
 }
 
 static void fill_prefetch_next(void)
 {
        if (using_prefetch) {
+               loopmode_begin();
                irc2ir();
                if (using_bus_error) {
                        copy_opcode();
                }
                fill_prefetch_1(m68k_pc_offset + 2);
+               loopmode_end();
        }
 }
 
 static void fill_prefetch_next_t(void)
 {
        if (using_prefetch) {
+               loopmode_begin();
                irc2ir();
                if (using_bus_error) {
                        copy_opcode();
                        strcat(bus_error_code, "\t\tif (regs.t1) opcode |= 0x10000;\n");
                }
                fill_prefetch_1(m68k_pc_offset + 2);
+               loopmode_end();
        }
 }
 
@@ -1089,6 +1112,7 @@ static void fill_prefetch_next_t(void)
 static void fill_prefetch_next_extra(const char *cond, const char *format, ...)
 {
        if (using_prefetch) {
+               loopmode_begin();
                irc2ir();
                if (using_bus_error) {
                        if (cond)
@@ -1103,6 +1127,7 @@ static void fill_prefetch_next_extra(const char *cond, const char *format, ...)
                        }
                }
                fill_prefetch_1(m68k_pc_offset + 2);
+               loopmode_end();
        }
 }
 
@@ -1110,6 +1135,7 @@ static void fill_prefetch_next_extra(const char *cond, const char *format, ...)
 static void fill_prefetch_next_after(int copy, const char *format, ...)
 {
        if (using_prefetch) {
+               loopmode_begin();
                irc2ir();
                printf("\topcode |= 0x20000;\n");
                bus_error_code[0] = 0;
@@ -1128,6 +1154,7 @@ static void fill_prefetch_next_after(int copy, const char *format, ...)
                                opcode_nextcopy = 1;
                        }
                }
+               loopmode_end();
        }
 }
 
@@ -2737,6 +2764,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        if (mode == Apdi && g_instr->size == sz_word && g_instr->mnemo != i_CLR) {
                                printf("\t\tm68k_areg(regs, %s) = %sa;\n", reg, name);
                        }
+                       if (mode == Apdi) {
+                               ;// printf("\t\tregs.read_buffer = 0;\n");
+                       }
                }
 
                if (g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) {
@@ -3894,11 +3924,11 @@ static void resetvars (void)
        dstblrmw = NULL;
        dstwlrmw = NULL;
        dstllrmw = NULL;
-       getpc = "m68k_getpc ()";
+       getpc = "m68k_getpc()";
 
        if (using_indirect > 0) {
                // tracer
-               getpc = "m68k_getpci ()";
+               getpc = "m68k_getpci()";
                if (using_mmu == 68030) {
                        // 68030 cache MMU / CE cache MMU
                        disp020 = "get_disp_ea_020_mmu030c";
@@ -3926,7 +3956,7 @@ static void resetvars (void)
                        srcwd = "get_word_mmu030c";
                        dstld = "put_long_mmu030c";
                        dstwd = "put_word_mmu030c";
-                       getpc = "m68k_getpci ()";
+                       getpc = "m68k_getpci()";
                } else if (!using_ce020 && !using_prefetch_020 && !using_ce) {
                        // generic + indirect
                        disp020 = "x_get_disp_ea_020";
@@ -4102,7 +4132,7 @@ static void resetvars (void)
                srcwd = "get_word_mmu030";
                dstld = "put_long_mmu030";
                dstwd = "put_word_mmu030";
-               getpc = "m68k_getpci ()";
+               getpc = "m68k_getpci()";
        } else if (using_mmu == 68040) {
                // 68040 MMU
                disp020 = "x_get_disp_ea_020";
@@ -4125,7 +4155,7 @@ static void resetvars (void)
                dstblrmw = "put_lrmw_byte_mmu040";
                dstwlrmw = "put_lrmw_word_mmu040";
                dstllrmw = "put_lrmw_long_mmu040";
-               getpc = "m68k_getpci ()";
+               getpc = "m68k_getpci()";
        } else if (using_mmu) {
                // 68060 MMU
                disp020 = "x_get_disp_ea_020";
@@ -4155,7 +4185,7 @@ static void resetvars (void)
                dstbrmw = "put_rmw_byte_mmu060";
                dstwrmw = "put_rmw_word_mmu060";
                dstlrmw = "put_rmw_long_mmu060";
-               getpc = "m68k_getpci ()";
+               getpc = "m68k_getpci()";
        } else if (using_ce) {
                // 68000 ce
                prefetch_word = "get_word_ce000_prefetch";
@@ -4167,7 +4197,7 @@ static void resetvars (void)
                srcb = "get_byte_ce000";
                dstb = "put_byte_ce000";
                do_cycles = "do_cycles_ce000";
-               getpc = "m68k_getpci ()";
+               getpc = "m68k_getpci()";
        } else if (using_prefetch) {
                // 68000 prefetch
                prefetch_word = "get_word_000_prefetch";
@@ -4179,7 +4209,7 @@ static void resetvars (void)
                dstw = "put_word_000";
                srcb = "get_byte_000";
                dstb = "put_byte_000";
-               getpc = "m68k_getpci ()";
+               getpc = "m68k_getpci()";
        } else {
                // generic + direct
                prefetch_long = "get_dilong";
@@ -4254,6 +4284,15 @@ static void gen_opcode (unsigned int opcode)
        bus_error_code2[0] = 0;
        opcode_nextcopy = 0;
 
+       loopmode = 0;
+       // 68010 loop mode available if
+       if (cpu_level == 1) {
+               loopmode = opcode_loop_mode(opcode);
+               if (curi->mnemo == i_DBcc || loopmode) {
+                       next_level_000();
+               }
+       }
+
        // do not unnecessarily create useless mmuop030
        // functions when CPU is not 68030
        if (curi->mnemo == i_MMUOP030 && cpu_level != 3 && !cpu_generic) {
@@ -6163,6 +6202,9 @@ 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) {
+                       printf("\tregs.loop_mode = false;\n");
+               }
                printf("\tuaecptr oldpc = %s;\n", getpc);
                addcycles000 (2);
                if (using_exception_3 && cpu_level >= 4) {
@@ -6184,6 +6226,33 @@ bccl_not68020:
                        write_return_cycles("\t\t", 0);
                        printf("\t\t}\n");
                }
+               // 68010 loop mode handling
+               if (cpu_level == 1) {
+                       printf("\t\tif(offs == -4 && !regs.t1 && loop_mode_table[regs.ird]) {\n");
+                       printf("\t\t\tregs.loop_mode = true;\n");
+                       printf("\t\t\tsrc = m68k_dreg(regs, srcreg);\n");
+                       genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src");
+                       addcycles000(2);
+                       printf("\t\t\tif (src) {\n");
+                       if (using_ce) {
+                               printf("\t\t\t\tloop_mode_table[regs.ird](regs.ird);\n");
+                       } else {
+                               printf("\t\t\t\tcount_cycles += loop_mode_table[regs.ird](regs.ird);\n");
+                       }
+                       setpc("oldpc");
+                       check_ipl();
+                       addcycles000(2);
+                       returncycles("\t\t\t\t", 4);
+                       printf("\t\t\t} else {\n");
+                       addcycles000(2);
+                       printf("\t\t\t}\n");
+                       printf("\t\t\tregs.loop_mode = false;\n");
+                       setpc("oldpc + %d", m68k_pc_offset);
+                       fill_prefetch_full_000_special();
+                       returncycles("\t\t\t", 6);
+                       printf("\t\t}\n");
+               }
+
                printf("\t");
                fill_prefetch_1(0);
                printf("\t");
index f47ab251a1b2232fd8f75f4c023f16a420dfc63e..ff9448260bc7a59ae5ad8ab83738acdd31083813 100644 (file)
@@ -85,6 +85,8 @@ struct comptbl {
 };
 #endif
 
+extern cpuop_func *loop_mode_table[];
+
 extern uae_u32 REGPARAM3 op_illg (uae_u32) REGPARAM;
 extern void REGPARAM3 op_unimpl (uae_u32) REGPARAM;
 
@@ -176,13 +178,14 @@ struct regstruct
        uae_u32 instruction_pc_user_exception;
        uae_u32 trace_pc;
 
-       uae_u16 irc, ir, db;
+       uae_u16 irc, ir, ird, db;
        volatile uae_atomic spcflags;
        uae_u32 last_prefetch;
        uae_u32 chipset_latch_rw;
        uae_u32 chipset_latch_read;
        uae_u32 chipset_latch_write;
        uae_u16 write_buffer, read_buffer;
+       bool loop_mode;
 
        uaecptr usp, isp, msp;
        uae_u16 sr;
@@ -270,7 +273,7 @@ struct cputracestruct
 {
        uae_u32 regs[16];
        uae_u32 usp, isp, pc;
-       uae_u16 ir, irc, sr, opcode;
+       uae_u16 ir, irc, ird, sr, opcode;
        int intmask, stopped, state;
 
        uae_u32 msp, vbr;
index cec523817fad49c5186ccf52a8dd48ff21b319eb..ed96393ee2de79e8860b20b51fe154b461ded545 100644 (file)
@@ -116,5 +116,6 @@ extern void read_table68k (void);
 extern void do_merges (void);
 extern int get_no_mismatches (void);
 extern int nr_cpuop_funcs;
+extern bool opcode_loop_mode(uae_u16 opcode);
 
 #endif /* UAE_READCPU_H */
index 78d950a21cfd513606fd3c657054a1d16ffce7a8..3501de41d11c5bd0b8e50af1a6e5e67260682239 100644 (file)
@@ -111,6 +111,7 @@ int movem_index2[256];
 int movem_next[256];
 
 cpuop_func *cpufunctbl[65536];
+cpuop_func *loop_mode_table[65536];
 
 struct cputbl_data
 {
@@ -1831,7 +1832,7 @@ static void build_cpufunctbl (void)
                struct instr *table = &table68k[opcode];
 
                if (table->mnemo == i_ILLG)
-                       continue;               
+                       continue;
 
                /* unimplemented opcode? */
                if (table->unimpclev > 0 && lvl >= table->unimpclev) {
@@ -1874,6 +1875,11 @@ static void build_cpufunctbl (void)
                        memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof(struct cputbl_data));
                        opcnt++;
                }
+
+               if (opcode_loop_mode(opcode)) {
+                       loop_mode_table[opcode] = cpufunctbl[opcode];
+               }
+
        }
        write_log (_T("Building CPU, %d opcodes (%d %d %d)\n"),
                opcnt, lvl,
@@ -3001,6 +3007,7 @@ static void ExceptionX (int nr, uaecptr address)
 {
        uaecptr pc = m68k_getpc();
        regs.exception = nr;
+       regs.loop_mode = 0;
        if (cpu_tracer) {
                cputrace.state = nr;
        }
@@ -4389,6 +4396,8 @@ static void m68k_run_1 (void)
                                do_cycles (cpu_cycles);
                                r->instruction_pc = m68k_getpc ();
                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
+                               if (!regs.loop_mode)
+                                       regs.ird = regs.opcode;
                                cpu_cycles = adjust_cycles (cpu_cycles);
                                if (r->spcflags) {
                                        if (do_specialties (cpu_cycles))
@@ -4434,6 +4443,7 @@ static void m68k_run_1_ce (void)
                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
                                        r->ir = cputrace.ir;
                                        r->irc = cputrace.irc;
+                                       r->ird = cputrace.ird;
                                        r->sr = cputrace.sr;
                                        r->usp = cputrace.usp;
                                        r->isp = cputrace.isp;
@@ -4471,6 +4481,7 @@ static void m68k_run_1_ce (void)
                                        cputrace.opcode = r->opcode;
                                        cputrace.ir = r->ir;
                                        cputrace.irc = r->irc;
+                                       cputrace.ird = r->ird;
                                        cputrace.sr = r->sr;
                                        cputrace.usp = r->usp;
                                        cputrace.isp = r->isp;
@@ -4497,6 +4508,8 @@ static void m68k_run_1_ce (void)
 
                                r->instruction_pc = m68k_getpc ();
                                (*cpufunctbl[r->opcode])(r->opcode);
+                               if (!regs.loop_mode)
+                                       regs.ird = regs.opcode;
                                wait_memory_cycles();
                                if (cpu_tracer) {
                                        cputrace.state = 0;
@@ -6225,6 +6238,7 @@ uae_u8 *restore_cpu (uae_u8 *src)
        } else {
                regs.stopped = 0;
        }
+       regs.ird = l >> 16;
        if (model >= 68010) {
                regs.dfc = restore_u32 ();
                regs.sfc = restore_u32 ();
@@ -6434,7 +6448,7 @@ uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
        else
                dstbak = dst = xmalloc (uae_u8, 10000);
 
-       save_u32 (2 | 4 | 16 | 32);
+       save_u32 (2 | 4 | 16 | 32 | 64);
        save_u16 (cputrace.opcode);
        for (int i = 0; i < 16; i++)
                save_u32 (cputrace.regs[i]);
@@ -6489,6 +6503,8 @@ uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
                save_u16(cputrace.pipeline_stop);
        }
 
+       save_u16(cputrace.ird);
+
        *len = dst - dstbak;
        cputrace.needendcycles = 1;
        return dstbak;
@@ -6576,6 +6592,9 @@ uae_u8 *restore_cpu_trace (uae_u8 *src)
                                cputrace.pipeline_r8[1] = restore_u16();
                                cputrace.pipeline_stop = restore_u16();
                        }
+                       if (v & 64) {
+                               cputrace.ird = restore_u16();
+                       }
                }
        }
 
@@ -6671,7 +6690,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
        save_u32 (!regs.s ? regs.regs[15] : regs.usp);  /* USP */
        save_u32 (regs.s ? regs.regs[15] : regs.isp);   /* ISP */
        save_u16 (regs.sr);                                                             /* SR/CCR */
-       save_u32 (regs.stopped ? CPUMODE_HALT : 0);             /* flags */
+       save_u32 ((regs.stopped ? CPUMODE_HALT : 0) | (regs.ird << 16)); /* flags + ird */
        if (model >= 68010) {
                save_u32 (regs.dfc);                    /* DFC */
                save_u32 (regs.sfc);                    /* SFC */
index c7896a0c10120e4bb3b657c56db9d83a39689bfc..00a263005766ce77af0d604971e7d3e34885bdd0 100644 (file)
@@ -16,39 +16,39 @@ int nr_cpuop_funcs;
 
 struct mnemolookup lookuptab[] = {
        { i_ILLG, _T("ILLEGAL"), NULL, 0 },
-       { i_OR, _T("OR"), NULL, 1 },
+       { i_OR, _T("OR"), NULL, 1 | 2 },
        { i_CHK, _T("CHK"), NULL, 0 },
        { i_CHK2, _T("CHK2"), NULL, 0 },
-       { i_AND, _T("AND"), NULL, 1 },
-       { i_EOR, _T("EOR"), NULL, 1 },
+       { i_AND, _T("AND"), NULL, 1 | 2 },
+       { i_EOR, _T("EOR"), NULL, 1 | 2 },
        { i_ORSR, _T("ORSR"), _T("OR"), 0 },
        { i_ANDSR, _T("ANDSR"), _T("AND"), 0 },
        { i_EORSR, _T("EORSR"), _T("EOR"), 0 },
-       { i_SUB, _T("SUB"), NULL, 1 },
-       { i_SUBA, _T("SUBA"), NULL, 1 },
-       { i_SUBX, _T("SUBX"), NULL, 0 },
-       { i_SBCD, _T("SBCD"), NULL, 0 },
-       { i_ADD, _T("ADD"), NULL, 1 },
-       { i_ADDA, _T("ADDA"), NULL, 1 },
-       { i_ADDX, _T("ADDX"), NULL, 0 },
-       { i_ABCD, _T("ABCD"), NULL, 0 },
-       { i_NEG, _T("NEG"), NULL, 1 },
-       { i_NEGX, _T("NEGX"), NULL, 1 },
-       { i_NBCD, _T("NBCD"), NULL, 0 },
-       { i_CLR, _T("CLR"), NULL, 1 },
-       { i_NOT, _T("NOT"), NULL, 1 },
-       { i_TST, _T("TST"), NULL, 1 },
+       { i_SUB, _T("SUB"), NULL, 1 | 2 },
+       { i_SUBA, _T("SUBA"), NULL, 1 | 2 },
+       { i_SUBX, _T("SUBX"), NULL, 0 | 2 },
+       { i_SBCD, _T("SBCD"), NULL, 0 | 2 },
+       { i_ADD, _T("ADD"), NULL, 1 | 2 },
+       { i_ADDA, _T("ADDA"), NULL, 1 | 2 },
+       { i_ADDX, _T("ADDX"), NULL, 0 | 2 },
+       { i_ABCD, _T("ABCD"), NULL, 0 | 2 },
+       { i_NEG, _T("NEG"), NULL, 1 | 2 },
+       { i_NEGX, _T("NEGX"), NULL, 1 | 2 },
+       { i_NBCD, _T("NBCD"), NULL, 0 | 2 },
+       { i_CLR, _T("CLR"), NULL, 1 | 2 },
+       { i_NOT, _T("NOT"), NULL, 1 | 2 },
+       { i_TST, _T("TST"), NULL, 1 | 2 },
        { i_BTST, _T("BTST"), NULL, 1 },
        { i_BCHG, _T("BCHG"), NULL, 1 },
        { i_BCLR, _T("BCLR"), NULL, 1 },
        { i_BSET, _T("BSET"), NULL, 1 },
-       { i_CMP, _T("CMP"), NULL, 1 },
-       { i_CMPM, _T("CMPM"), NULL, 1 },
-       { i_CMPA, _T("CMPA"), NULL, 1 },
+       { i_CMP, _T("CMP"), NULL, 1 | 2 },
+       { i_CMPM, _T("CMPM"), NULL, 1 | 2 },
+       { i_CMPA, _T("CMPA"), NULL, 1 | 2 },
        { i_MVPRM, _T("MVPRM"), _T("MOVEP"), 0 },
        { i_MVPMR, _T("MVPMR"), _T("MOVEP"), 0 },
-       { i_MOVE, _T("MOVE"), NULL, 1 },
-       { i_MOVEA, _T("MOVEA"), NULL, 1 },
+       { i_MOVE, _T("MOVE"), NULL, 1 | 2 },
+       { i_MOVEA, _T("MOVEA"), NULL, 1 | 2 },
        { i_MVSR2, _T("MVSR2"), _T("MOVE"), 0 },
        { i_MV2SR, _T("MV2SR"), _T("MOVE"), 0 },
        { i_SWAP, _T("SWAP"), NULL, 0 },
@@ -89,14 +89,14 @@ struct mnemolookup lookuptab[] = {
        { i_ROR, _T("ROR"), NULL, 0 },
        { i_ROXL, _T("ROXL"), NULL, 1 },
        { i_ROXR, _T("ROXR"), NULL, 1 },
-       { i_ASRW, _T("ASRW"), _T("ASR"), 1 },
-       { i_ASLW, _T("ASLW"), _T("ASL"), 1 },
-       { i_LSRW, _T("LSRW"), _T("LSR"), 1 },
-       { i_LSLW, _T("LSLW"), _T("LSL"), 1 },
-       { i_ROLW, _T("ROLW"), _T("ROL"), 1 },
-       { i_RORW, _T("RORW"), _T("ROR"), 1 },
-       { i_ROXLW, _T("ROXLW"), _T("ROXL"), 1 },
-       { i_ROXRW, _T("ROXRW"), _T("ROXR"), 1 },
+       { i_ASRW, _T("ASRW"), _T("ASR"), 1 | 2 },
+       { i_ASLW, _T("ASLW"), _T("ASL"), 1 | 2 },
+       { i_LSRW, _T("LSRW"), _T("LSR"), 1 | 2 },
+       { i_LSLW, _T("LSLW"), _T("LSL"), 1 | 2 },
+       { i_ROLW, _T("ROLW"), _T("ROL"), 1 | 2 },
+       { i_RORW, _T("RORW"), _T("ROR"), 1 | 2 },
+       { i_ROXLW, _T("ROXLW"), _T("ROXL"), 1 | 2 },
+       { i_ROXRW, _T("ROXRW"), _T("ROXR"), 1 | 2 },
 
        { i_MOVE2C, _T("MOVE2C"), _T("MOVEC"), 0 },
        { i_MOVEC2, _T("MOVEC2"), _T("MOVEC"), 0 },
@@ -882,3 +882,36 @@ int get_no_mismatches (void)
 {
        return imismatch;
 }
+
+static int isreg(amodes mode)
+{
+       if (mode == Dreg || mode == Areg)
+               return 1;
+       return 0;
+}
+
+bool opcode_loop_mode(uae_u16 opcode)
+{
+       instr *c = &table68k[opcode];
+       bool loopmode = false;
+       int i;
+       for (i = 0; lookuptab[i].name[0]; i++) {
+               if (c->mnemo == lookuptab[i].mnemo)
+                       break;
+       }
+       if (lookuptab[i].flags & 2) {
+               // Source is Dn,An,(An),(An)+,-(An)
+               // Destination is Dn,An,(An),(An)+,-(An)
+               // Both source and destination must not be Dn or An.
+               // RMW instruction must not be Dn or An
+               if (((isreg(c->smode) || c->smode == Aind || c->smode == Apdi || c->smode == Aipi)) &&
+                       ((!c->duse && !isreg(c->smode)) || (c->duse && (isreg(c->dmode) || c->dmode == Aind || c->dmode == Apdi || c->dmode == Aipi))) &&
+                       (!c->duse || (isreg(c->smode) && !isreg(c->dmode)) || (!isreg(c->smode) && isreg(c->dmode)) || (!isreg(c->smode) && !isreg(c->dmode)))) {
+                       loopmode = true;
+               }
+               if (c->mnemo == i_MOVE && isreg(c->dmode)) {
+                       loopmode = false;
+               }
+       }
+       return loopmode;
+}