]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68010 address error updates.
authorToni Wilen <twilen@winuae.net>
Wed, 1 Jan 2020 18:02:22 +0000 (20:02 +0200)
committerToni Wilen <twilen@winuae.net>
Wed, 1 Jan 2020 18:02:22 +0000 (20:02 +0200)
cputest.cpp
cputest/main.c
gencpu.cpp
include/cpu_prefetch.h
include/newcpu.h
newcpu.cpp

index defefe127c82e1a513e1b48506ec6d627f6ea48b..f7641e94cd4bead892fd18d338cf426ad9bb86b8 100644 (file)
@@ -846,8 +846,6 @@ static void doexcstack(void)
                        ssw |= (test_exception_opcode & 0x10000) ? 0x0400 : 0x0000; // HB
                        ssw |= test_exception_3_size == 0 ? 0x0200 : 0x0000; // BY
                        ssw |= test_exception_3_w ? 0x0000 : 0x0100; // RW
-                       if (test_exception_opcode & 0x20000)
-                               ssw &= 0x00ff;
                        regs.mmu_fault_addr = test_exception_addr;
                        Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x08);
                        SPCFLAG_DOTRACE = 0;
index e7155aab61083c0f1a0953547512e75805fc9d5f..0b314305ca0319b985b3e941598ac907a2d9ab93 100644 (file)
@@ -1252,8 +1252,14 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                        }
                } else if (!last_exception_extra && excnum != 9) {
                        if (regs->tracecnt > 0) {
-                               sprintf(outbp, "Got unexpected trace exception\n");
+                               uae_u32 ret = (regs->tracedata[1] << 16) | regs->tracedata[2];
+                               uae_u16 sr = regs->tracedata[0];
+                               sprintf(outbp, "Got unexpected trace exception: SR=%04x PC=%08lx.\n", sr, ret);
                                outbp += strlen(outbp);
+                               if (excnum >= 2) {
+                                       sprintf(outbp, "Exception %ld also pending.\n", excnum);
+                                       outbp += strlen(outbp);
+                               }
                                *experr = 1;
                        }
                } else if (last_exception_extra) {
@@ -1391,9 +1397,17 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                                // read input buffer may contain either actual data read from memory or previous read data
                                // this depends on hardware, cpu does dummy read cycle and some hardware returns memory data, some ignore it.
                                memcpy(alternate_exception1, exc, exclen);
-                               alternate_exception1[20] = *p++;
-                               alternate_exception1[21] = *p++;
-                               alts = 1;
+                               memcpy(alternate_exception2, exc, exclen);
+                               alternate_exception1[20] = p[0];
+                               alternate_exception1[21] = p[1];
+                               memcpy(alternate_exception3, alternate_exception1, exclen);
+                               // same with instruction input buffer if branch instruction generates address error
+                               alternate_exception2[24] = p[0];
+                               alternate_exception2[25] = p[1];
+                               alternate_exception3[24] = p[0];
+                               alternate_exception3[25] = p[1];
+                               p += 2;
+                               alts = 3;
                                break;
                        case 0x0a:
                        case 0x0b:
index c8d08bfac58876fcc38a662295dded7e6500939c..33ead005b8e38e55995f176c938dfd8f1f3621ce 100644 (file)
@@ -851,7 +851,9 @@ static void fill_prefetch_bcc(void)
                return;
        if (using_bus_error) {
                copy_opcode();
-               printf("\tif(regs.t1) opcode |= 0x10000;\n");
+               if (cpu_level == 0) {
+                       printf("\tif(regs.t1) opcode |= 0x10000;\n");
+               }
        }
        printf("\t%s(%d);\n", prefetch_word, m68k_pc_offset + 2);
        count_read++;
@@ -911,10 +913,12 @@ static void fill_prefetch_full_ntx(int beopcode)
                irc2ir ();
                if (beopcode) {
                        copy_opcode();
-                       if (beopcode == 2)
-                               printf("\tif(regs.t1) opcode |= 0x10000;\n");
-                       if (beopcode == 3)
-                               printf("\tif(t1) opcode |= 0x10000;\n");
+                       if (cpu_level == 0) {
+                               if (beopcode == 2)
+                                       printf("\tif(regs.t1) opcode |= 0x10000;\n");
+                               if (beopcode == 3)
+                                       printf("\tif(t1) opcode |= 0x10000;\n");
+                       }
                        fill_prefetch_1(2);
                } else {
                        fill_prefetch_1_empty(2);
@@ -956,8 +960,9 @@ static void fill_prefetch_full(int beopcode)
                irc2ir ();
                if (beopcode) {
                        copy_opcode();
-                       if (beopcode > 1)
+                       if (beopcode > 1 && cpu_level == 0) {
                                printf("\tif(regs.t1) opcode |= 0x10000;\n");
+                       }
                        fill_prefetch_1(2);
                } else {
                        fill_prefetch_1_empty(2);
@@ -986,10 +991,12 @@ static void fill_prefetch_full_000_special(void)
        irc2ir();
        if (using_bus_error) {
                copy_opcode();
-               if (g_instr->mnemo == i_RTE) {
-                       printf("\tif(oldt1) opcode |= 0x10000;\n");
-               } else {
-                       printf("\tif(regs.t1) opcode |= 0x10000;\n");
+               if (cpu_level == 0) {
+                       if (g_instr->mnemo == i_RTE) {
+                               printf("\tif(oldt1) opcode |= 0x10000;\n");
+                       } else {
+                               printf("\tif(regs.t1) opcode |= 0x10000;\n");
+                       }
                }
        }
        printf("\t%s(%d);\n", prefetch_word, 2);
@@ -1031,17 +1038,6 @@ static void fill_prefetch_0 (void)
        ir2irc = 0;
 }
 
-static void dummy_prefetch (void)
-{
-       int o = m68k_pc_offset + 2;
-       if (!using_prefetch)
-               return;
-       printf("\t%s(%d);\n", srcwi, o);
-       count_read++;
-       insn_n_cycles += 4;
-       check_prefetch_bus_error(o, 0);
-}
-
 static void loopmode_begin(void)
 {
        if (loopmode) {
@@ -1051,8 +1047,11 @@ static void loopmode_begin(void)
 static void loopmode_end(void)
 {
        if (loopmode) {
-               printf("\t} else {\n");
-               addcycles000(2);
+               int m = g_instr->mnemo;
+               if (g_instr->dmode == Apdi || m != i_MOVE) {
+                       printf("\t} else {\n");
+                       addcycles000(2);
+               }
                printf("\t}\n");
        }
 }
@@ -1070,7 +1069,9 @@ static void fill_prefetch_next_noopcodecopy(const char *format, ...)
                                _vsnprintf(bus_error_code, sizeof(bus_error_code) - 1, format, parms);
                                va_end(parms);
                        }
-                       printf("\topcode |= 0x20000;\n");
+                       if (cpu_level == 0) {
+                               printf("\topcode |= 0x20000;\n");
+                       }
                }
                fill_prefetch_1(m68k_pc_offset + 2);
                if (using_bus_error) {
@@ -1100,7 +1101,9 @@ static void fill_prefetch_next_t(void)
                irc2ir();
                if (using_bus_error) {
                        copy_opcode();
-                       strcat(bus_error_code, "\t\tif (regs.t1) opcode |= 0x10000;\n");
+                       if (cpu_level == 0) {
+                               strcat(bus_error_code, "\t\tif (regs.t1) opcode |= 0x10000;\n");
+                       }
                }
                fill_prefetch_1(m68k_pc_offset + 2);
                loopmode_end();
@@ -1136,7 +1139,9 @@ static void fill_prefetch_next_after(int copy, const char *format, ...)
        if (using_prefetch) {
                loopmode_begin();
                irc2ir();
-               printf("\topcode |= 0x20000;\n");
+               if (cpu_level == 0) {
+                       printf("\topcode |= 0x20000;\n");
+               }
                bus_error_code[0] = 0;
                if (format) {
                        va_list parms;
@@ -1163,7 +1168,9 @@ static void fill_prefetch_next_skipopcode(void)
        if (using_prefetch) {
                irc2ir();
                if (using_bus_error) {
-                       printf("\topcode |= 0x20000;\n");
+                       if (cpu_level == 0) {
+                               printf("\topcode |= 0x20000;\n");
+                       }
                }
                fill_prefetch_1(m68k_pc_offset + 2);
        }
@@ -1226,6 +1233,27 @@ static void incpc (const char *format, ...)
                printf("\tm68k_incpc(%s);\n", buffer);
 }
 
+static void dummy_prefetch(const char *newpc, const char *oldpc)
+{
+       if (using_prefetch && cpu_level == 1) {
+               if (!newpc && !oldpc) {
+                       printf("\t\t%s((m68k_getpci() & 1) ? -1 : 0);\n", prefetch_word);
+               } else {
+                       if (newpc) {
+                               if (!oldpc)
+                                       printf("\t\tuaecptr d_oldpc = m68k_getpci();\n");
+                               setpc("%s & ~1", newpc);
+                       }
+                       printf("\t\t%s(0);\n", prefetch_word);
+                       if (oldpc) {
+                               setpc(oldpc);
+                       } else if (newpc) {
+                               setpc("d_oldpc");
+                       }
+               }
+       }
+}
+
 static void sync_m68k_pc (void)
 {
        m68k_pc_offset_old = m68k_pc_offset;
@@ -1495,7 +1523,9 @@ static void move_68000_bus_error(int offset, int size, int *setapdi, int *fcmode
 
                if (dmode == Apdi) {
 
-                       printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
+                       if (cpu_level == 0) {
+                               printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
+                       }
 
                } else if (dmode == Aipi) {
 
@@ -1507,7 +1537,9 @@ static void move_68000_bus_error(int offset, int size, int *setapdi, int *fcmode
 
                if (dmode == Apdi) {
 
-                       printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
+                       if (cpu_level == 0) {
+                               printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
+                       }
 
                } else if (dmode == Aipi) {
 
@@ -1663,6 +1695,7 @@ static int do_bus_error_fixes(const char *name, int offset, int write)
                        // CMPM.L (an)+,(an)+: first increased normally, second not increased
                        printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
                }
+               break;
        case 4:
        case -4:
                if ((g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) && g_instr->size == sz_long) {
@@ -1764,7 +1797,9 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                        printf("\t\tm68k_areg(regs, srcreg) = olda;\n");
                }
                if (mnemo == i_PEA && write && offset && g_instr->smode != absw && g_instr->smode != absl) {
-                       printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
+                       if (cpu_level == 0) {
+                               printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
+                       }
                }
 
                if (cpu_level == 1 && g_instr->mnemo == i_MVSR2 && !write) {
@@ -1777,7 +1812,7 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                }
 
                // write causing bus error and trace: set I/N
-               if (write && g_instr->size <= sz_word &&
+               if (write && g_instr->size <= sz_word && cpu_level == 0 &&
                        mnemo != i_MOVE &&
                        mnemo != i_BSR &&
                        mnemo != i_LINK &&
@@ -2259,7 +2294,6 @@ static void maybeaddop_ce020 (int flags)
                addop_ce020 (curi_ce020, subhead_ce020, flags);
 }
 
-
 // Handle special MOVE.W/.L condition codes when destination write causes address error.
 static void move_68000_address_error(int size, int *setapdi, int *fcmodeflags)
 {
@@ -2362,6 +2396,110 @@ static void move_68000_address_error(int size, int *setapdi, int *fcmodeflags)
        }
 }
 
+// Handle special MOVE.W/.L condition codes when destination write causes address error.
+static void move_68010_address_error(int size, int *setapdi, int *fcmodeflags)
+{
+       int smode = g_instr->smode;
+       int dmode = g_instr->dmode;
+
+       if (size == sz_word) {
+               // Word MOVE is relatively simply
+               int set_ccr = 0;
+               switch (smode)
+               {
+               case Dreg:
+               case Areg:
+               case imm:
+                       if (dmode == Apdi || dmode == Ad16 || dmode == Ad8r || dmode == absw || dmode == absl)
+                               set_ccr = 1;
+                       break;
+               case Aind:
+               case Aipi:
+               case Apdi:
+               case Ad16:
+               case PC16:
+               case Ad8r:
+               case PC8r:
+               case absw:
+               case absl:
+                       if (dmode == Aind || dmode == Aipi || dmode == Apdi || dmode == Ad16 || dmode == Ad8r || dmode == absw || dmode == absl)
+                               set_ccr = 1;
+                       break;
+               }
+               if (dmode == Apdi) {
+                       dummy_prefetch(NULL, NULL);
+               } else if (dmode == absl && smode >= Aind && smode < imm) {
+                       printf("\t\tregs.irc = dsta >> 16;\n");
+               }
+               if (set_ccr) {
+                       printf("\t\tccr_68000_word_move_ae_normal((uae_s16)(src));\n");
+               }
+       } else {
+               // Long MOVE is much more complex..
+               int set_ccr = 0;
+               int set_high_word = 0;
+               int set_low_word = 0;
+               switch (smode)
+               {
+               case Dreg:
+               case Areg:
+               case imm:
+                       if (dmode == Aind || dmode == Aipi) {
+                               set_ccr = 0;
+                       } else if (dmode == Ad16 || dmode == Ad8r) {
+                               set_high_word = 1;
+                       } else if (dmode == Apdi || dmode == absw || dmode == absl) {
+                               set_ccr = 1;
+                       }
+                       break;
+               case Ad16:
+               case PC16:
+               case Ad8r:
+               case PC8r:
+               case absw:
+               case absl:
+                       if (dmode == Apdi || dmode == Ad16 || dmode == Ad8r || dmode == absw) {
+                               set_ccr = 1;
+                       } else if (dmode == Aind || dmode == Aipi || dmode == absl) {
+                               set_low_word = 1;
+                       } else {
+                               set_low_word = 2;
+                       }
+                       break;
+               case Aind:
+               case Aipi:
+               case Apdi:
+                       if (dmode == Aind || dmode == Aipi || dmode == absl) {
+                               set_low_word = 1;
+                       } else {
+                               set_ccr = 1;
+                       }
+                       break;
+               }
+
+               if (dmode == Apdi) {
+                       dummy_prefetch(NULL, NULL);
+                       *setapdi = 0;
+               } else if (dmode == absl && smode >= Aind && smode < imm) {
+                       printf("\t\tregs.irc = dsta >> 16;\n");
+               }
+
+               if (set_low_word == 1) {
+                       // Low word: Z and N
+                       printf("\t\tccr_68000_long_move_ae_LZN(src);\n");
+               } else if (set_low_word == 2) {
+                       // Low word: N only
+                       printf("\t\tccr_68000_long_move_ae_LN(src);\n");
+               } else if (set_high_word) {
+                       // High word: N and Z clear.
+                       printf("\t\tccr_68000_long_move_ae_HNZ(src);\n");
+               } else if (set_ccr) {
+                       // Set normally.
+                       printf("\t\tccr_68000_long_move_ae_normal(src);\n");
+               }
+       }
+}
+
 /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
 * the calling routine handles Apdi and Aipi modes.
 * gb-- movem == 2 means the same thing but for a MOVE16 instruction */
@@ -2461,7 +2599,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                printf("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf("\t%sa = m68k_areg(regs, %s);\n", name, reg);
-               addr = true;
                break;
        case Aipi: // (An)+
                switch (fetchmode)
@@ -2475,7 +2612,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                printf("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf("\t%sa = m68k_areg(regs, %s);\n", name, reg);
-               addr = true;
                break;
        case Apdi: // -(An)
                switch (fetchmode)
@@ -2511,7 +2647,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        if (size == sz_long)
                                pc_68000_offset_fetch -= 2;
                }
-               addr = true;
                break;
        case Ad16: // (d16,An)
                printf("\tuaecptr %sa;\n", name);
@@ -2685,8 +2820,11 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                term ();
        }
 
+       if (getv == 2 && g_srcname[0] && g_srcname[strlen(g_srcname) - 1] == 'a' && g_instr->mnemo != i_PEA) {
+               g_srcname[strlen(g_srcname) - 1] = 0;
+       }
        if (g_srcname[0] == 0) {
-               if (addr)
+               if (addr || g_instr->mnemo == i_PEA)
                        strcpy(g_srcname, namea);
                else
                        strcpy(g_srcname, name);        
@@ -2750,7 +2888,8 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
 
                if (cpu_level == 1) {
                        // 68010 does dummy access
-                       printf("\t\tuae_s16 d_%s = %s(%sa & ~1);\n", name, srcw, name);
+                       if (getv != 2)
+                               printf("\t\tuae_s16 d_%s = %s(%sa & ~1);\n", name, srcw, name);
                        if (abs(bus_error_reg_add) == 4)
                                bus_error_reg_add = 0;
                        // 68010 CLR <memory>: pre and post are not added yet
@@ -2760,7 +2899,13 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                if (mode == Apdi)
                                        bus_error_reg_add = 0;
                        }
-                       do_bus_error_fixes(name, 0, getv == 2);
+                       if (g_instr->mnemo == i_MOVE || g_instr->mnemo == i_MOVEA) {
+                               if (getv != 2) {
+                                       do_bus_error_fixes(name, 0, getv == 2);
+                               }
+                       } else {
+                               do_bus_error_fixes(name, 0, getv == 2);
+                       }
                        // x,-(an): an is modified
                        if (mode == Apdi && g_instr->size == sz_word && g_instr->mnemo != i_CLR) {
                                printf("\t\tm68k_areg(regs, %s) = %sa;\n", reg, name);
@@ -2785,7 +2930,11 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
 
                if (g_instr->mnemo == i_MOVE) {
                        if (getv == 2) {
-                               move_68000_address_error(size, &setapdiback, &fcmodeflags);
+                               if (cpu_level == 0) {
+                                       move_68000_address_error(size, &setapdiback, &fcmodeflags);
+                               } else {
+                                       move_68010_address_error(size, &setapdiback, &fcmodeflags);
+                               }
                        }
                } else if (g_instr->mnemo == i_MVSR2) {
                        // If MOVE from SR generates address error exception,
@@ -2809,7 +2958,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        printf("\t\t%sa += %d;\n", name, flags & GF_REVERSE2 ? -2 : 2);
 
                if (exp3rw) {
-                       const char *shift = size == sz_long ? " >> 16" : "";
+                       const char *shift = (size == sz_long && !(flags & GF_REVERSE)) ? " >> 16" : "";
                        printf("\t\texception3_write(opcode, %sa, %d, %s%s, %d);\n",
                                name, size, g_srcname, shift,
                                // PC-relative: FC=2
@@ -3528,10 +3677,11 @@ static void movem_ex3(int write)
                                        printf("\t\t\tsrcav = m68k_dreg(regs, movem_index2[dmask]);\n");
                                        printf("\t\t}\n");
                                } else {
+                                       int shift = g_instr->size == sz_long ? 16 : 0;
                                        printf("\t\tif(dmask) {\n");
-                                       printf("\t\t\tsrcav = m68k_dreg(regs, movem_index1[dmask]);\n");
+                                       printf("\t\t\tsrcav = m68k_dreg(regs, movem_index1[dmask]) >> %d;\n", shift);
                                        printf("\t\t} else if (amask) {\n");
-                                       printf("\t\t\tsrcav = m68k_areg(regs, movem_index1[amask]);\n");
+                                       printf("\t\t\tsrcav = m68k_areg(regs, movem_index1[amask]) >> %d;\n", shift);
                                        printf("\t\t}\n");
                                }
                                if (g_instr->dmode == Aind || g_instr->dmode == Apdi || g_instr->dmode == Aipi) {
@@ -3542,8 +3692,8 @@ static void movem_ex3(int write)
                        // MOVEM from memory will generate address error
                        // exception if mask is zero and EA is odd.
                        printf("\tif (srca & 1) {\n");
-                       if (g_instr->dmode == PC16 || g_instr->dmode == PC8r) {
-                               printf("\t\topcode |= 0x01020000;\n");
+                       if ((g_instr->dmode == PC16 || g_instr->dmode == PC8r) && cpu_level == 0) {
+                               printf("\t\topcode |= 0x00020000;\n");
                        }
                        printf("\t\tuaecptr srcav = srca;\n");
                        if (cpu_level == 1) {
@@ -4400,7 +4550,7 @@ static void gen_opcode (unsigned int opcode)
        case i_ANDSR:
        case i_EORSR:
                printf("\tMakeSR();\n");
-               if (cpu_level <= 1)
+               if (cpu_level == 0)
                        printf("\tint t1 = regs.t1;\n");
                genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                if (curi->size == sz_byte) {
@@ -4903,13 +5053,26 @@ static void gen_opcode (unsigned int opcode)
                                addcycles000(2);
                        if (!isreg(curi->smode) && using_exception_3 && curi->size != sz_byte && (using_prefetch || using_ce)) {
                                printf("\tif(srca & 1) {\n");
-                               if (curi->smode == Aipi) {
-                                       printf("\t\tm68k_areg(regs, srcreg) -= %d;\n", 1 << curi->size);
-                               } else if (curi->smode == Apdi) {
-                                       printf("\t\tm68k_areg(regs, srcreg) += %d;\n", 1 << curi->size);
-                               } else if (curi->smode >= Ad16) {
-                                       printf("\t%s(%d);\n", prefetch_word, m68k_pc_offset + 2);
-                                       genflags(flag_logical, curi->size, "0", "", "");
+                               if (curi->size == sz_word) {
+                                       if (curi->smode == Aipi) {
+                                               printf("\t\tm68k_areg(regs, srcreg) -= 2;\n");
+                                       } else if (curi->smode == Apdi) {
+                                               printf("\t\tm68k_areg(regs, srcreg) += 2;\n");
+                                       } else if (curi->smode >= Ad16) {
+                                               printf("\t%s(%d);\n", prefetch_word, m68k_pc_offset + 2);
+                                               genflags(flag_logical, curi->size, "0", "", "");
+                                       }
+                               } else {
+                                       if (curi->smode == Aipi) {
+                                               printf("\t\tm68k_areg(regs, srcreg) -= 4;\n");
+                                       } else if (curi->smode == Apdi) {
+                                               printf("\t\tm68k_areg(regs, srcreg) += 4;\n");
+                                               printf("\t\tsrca += 2;\n");
+                                       } else if (curi->smode >= Ad16) {
+                                               printf("\t\tsrca += 2;\n");
+                                               printf("\t%s(%d);\n", prefetch_word, m68k_pc_offset + 2);
+                                               genflags(flag_logical, curi->size, "0", "", "");
+                                       }
                                }
                                printf("\t\texception3_write(opcode, srca, 1, 0, 1);\n");
                                write_return_cycles("\t\t", 0);
@@ -5216,8 +5379,6 @@ static void gen_opcode (unsigned int opcode)
                                genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
 
                                flags = GF_MOVE | GF_APDI;
-                               //if (curi->size == sz_long && (curi->smode == Dreg || curi->smode == Areg))
-                               //      flags &= ~GF_APDI;
                                flags |= dualprefetch ? GF_NOREFILL : 0;
                                if (curi->dmode == Apdi && curi->size == sz_long)
                                        flags |= GF_REVERSE;
@@ -5348,7 +5509,9 @@ static void gen_opcode (unsigned int opcode)
                printf("\tMakeSR();\n");
                if (isreg (curi->smode)) {
                        if (cpu_level == 0 && curi->size == sz_word) {
-                               fill_prefetch_next_after(1, "\t\tMakeSR();\n\t\tm68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | ((regs.sr) & 0xffff);\n");
+                               fill_prefetch_next_after(1,
+                                       "\t\tMakeSR();\n"
+                                       "\t\tm68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | ((regs.sr) & 0xffff);\n");
                        } else {
                                fill_prefetch_next_after(1, NULL);
                        }
@@ -5364,7 +5527,7 @@ static void gen_opcode (unsigned int opcode)
                }
                if (!isreg(curi->smode) && cpu_level == 1 && using_exception_3 && (using_prefetch || using_ce)) {
                        printf("\tif(srca & 1) {\n");
-                       printf("\t\texception3_write(opcode, srca, 1, regs.sr, 1);\n");
+                       printf("\t\texception3_write(opcode, srca, 1, regs.sr & 0x%x, 1);\n", curi->size == sz_byte ? 0x00ff : 0xffff);
                        write_return_cycles("\t\t", 0);
                        printf("\t}\n");
                }
@@ -5376,7 +5539,7 @@ static void gen_opcode (unsigned int opcode)
                break;
        case i_MV2SR: // MOVE TO SR
                genamode (curi, curi->smode, "srcreg", sz_word, "src", 1, 0, 0);
-               if (cpu_level <= 1)
+               if (cpu_level == 0)
                        printf("\tint t1 = regs.t1;\n");
                if (curi->size == sz_byte) {
                        // MOVE TO CCR
@@ -5539,13 +5702,11 @@ static void gen_opcode (unsigned int opcode)
        case i_RTE:
                addop_ce020 (curi, 0, 0);
                next_level_000 ();
-               if (cpu_level <= 1) {
-                       if (cpu_level <= 1 && using_exception_3) {
-                               printf("\tif (m68k_areg(regs, 7) & 1) {\n");
-                               printf("\t\texception3_read(opcode, m68k_areg(regs, 7), 1, 1);\n");
-                               write_return_cycles("\t\t", 0);
-                               printf("\t}\n");
-                       }
+               if (cpu_level <= 1 && using_exception_3) {
+                       printf("\tif (m68k_areg(regs, 7) & 1) {\n");
+                       printf("\t\texception3_read(opcode, m68k_areg(regs, 7), 1, 1);\n");
+                       write_return_cycles("\t\t", 0);
+                       printf("\t}\n");
                }
                if (cpu_level == 0) {
                        // 68000
@@ -5569,48 +5730,42 @@ static void gen_opcode (unsigned int opcode)
                        int old_brace_level = n_braces;
                        printf("\tuaecptr oldpc = %s;\n", getpc);
                        printf("\tuae_u16 newsr; uae_u32 newpc;\n");
-                       printf("\tuae_u16 oldt1 = regs.t1;\n");
-                       printf("\tfor (;;) {\n");
-                       printf("\t\tuaecptr a = m68k_areg(regs, 7);\n");
-                       printf("\t\tuae_u16 sr = %s(a);\n", srcw);
+                       printf("\tuaecptr a = m68k_areg(regs, 7);\n");
+                       printf("\tuae_u16 format = %s(a + 2 + 4);\n", srcw);
+                       count_read++;
+                       check_bus_error("", 6, 0, 1, NULL, 1);
+                       printf("\tint frame = format >> 12;\n");
+                       printf("\tint offset = 8;\n");
+                       printf("\tif (frame == 0x0) {\n");
+                       printf("\t\tm68k_areg(regs, 7) += offset;\n");
+                       printf("\t} else if (frame == 0x8) {\n");
+                       printf("\t\tm68k_areg(regs, 7) += offset + 50;\n");
+                       printf("\t} else {\n");
+                       printf("\t\tSET_NFLG(((uae_s16)format) < 0); \n");
+                       printf("\t\tSET_ZFLG(format == 0);\n");
+                       printf("\t\tSET_VFLG(0);\n");
+                       printf("\t\tException_cpu(14);\n");
+                       write_return_cycles("\t\t", 0);
+                       printf("\t}\n");
+                       printf("\tuae_u16 sr = %s(a);\n", srcw);
                        count_read++;
                        check_bus_error("", 0, 0, 1, NULL, 1);
-                       printf("\t\tuae_u32 pc = %s(a + 2) << 16;\n", srcw);
+                       printf("\tuae_u32 pc = %s(a + 2) << 16;\n", srcw);
                        count_read++;
                        check_bus_error("", 2, 0, 1, NULL, 1);
-                       printf("\t\tpc |= % s(a + 4); \n", srcw);
+                       printf("\tpc |= % s(a + 4); \n", srcw);
                        count_read++;
                        check_bus_error("", 4, 0, 1, NULL, 1);
-                       printf("\t\tuae_u16 format = %s(a + 2 + 4);\n", srcw);
-                       count_read++;
-                       check_bus_error("", 6, 0, 1, NULL, 1);
-                       printf("\t\tint frame = format >> 12;\n");
-                       printf("\t\tint offset = 8;\n");
-                       printf("\t\tnewsr = sr; newpc = pc;\n");
-                       printf("\t\tif (frame == 0x0) {\n");
-                       printf("\t\t\tm68k_areg(regs, 7) += offset;\n");
-                       printf("\t\t\tbreak;\n");
-                       printf("\t\t} else if (frame == 0x8) {\n");
-                       printf("\t\t\tm68k_areg(regs, 7) += offset + 50;\n");
-                       printf("\t\t\tbreak;\n");
-                       printf("\t\t} else {\n");
-                       printf("\t\t\tSET_NFLG(((uae_s16)format) < 0); \n");
-                       printf("\t\t\tSET_ZFLG(format == 0);\n");
-                       printf("\t\t\tSET_VFLG(0);\n");
-                       printf("\t\t\tException_cpu(14);\n");
-                       write_return_cycles("\t\t", 0);
-                       printf("\t\t}\n");
-                       printf("\t\tregs.sr = newsr;\n");
-                       printf("\t\tMakeFromSR();\n");
-                       printf("\t}\n");
                    pop_braces (old_brace_level);
-                   printf("\tregs.sr = newsr;\n");
+                       printf("\tregs.sr = sr;\n");
                        makefromsr();
-                   printf("\tif (newpc & 1) {\n");
-                   printf("\t\texception3i(opcode, newpc);\n");
+                       printf("\tif (pc & 1) {\n");
+                       dummy_prefetch("pc", "oldpc");
+                       printf("\texception3i(opcode, pc);\n");
                        write_return_cycles("\t\t", 0);
                        printf("\t}\n");
-                   setpc ("newpc");
+                       printf("\tnewsr = sr; newpc = pc;\n");
+                       setpc ("newpc");
                        if (using_debugmem) {
                                printf("\tbranch_stack_pop_rte(oldpc);\n");
                        }
@@ -5740,7 +5895,7 @@ static void gen_opcode (unsigned int opcode)
                if (cpu_level >= 4) {
                        printf("\t\tm68k_areg(regs, 7) -= 4 + offs;\n");
                }
-               printf("\t\texception3i (0x%04X, pc);\n", opcode);
+               printf("\t\texception3i(0x%04X, pc);\n", opcode);
                write_return_cycles("\t\t", 0);
                printf("\t}\n");
                setpc ("pc");
@@ -5855,11 +6010,14 @@ static void gen_opcode (unsigned int opcode)
                }
            printf("\tif (%s & 1) {\n", getpc);
                printf("\t\tuaecptr faultpc = %s;\n", getpc);
-               setpc ("pc");
+               if (cpu_level == 1) {
+                       dummy_prefetch(NULL, NULL);
+               }
+               setpc("pc");
                if (cpu_level >= 4) {
                        printf("\t\tm68k_areg(regs, 7) -= 4;\n");
                }
-               printf("\t\texception3i (0x%04X, faultpc);\n", opcode);
+               printf("\t\texception3i(0x%04X, faultpc);\n", opcode);
                write_return_cycles("\t\t", 0);
                printf("\t}\n");
                clear_m68k_offset();
@@ -5898,7 +6056,7 @@ static void gen_opcode (unsigned int opcode)
                if (cpu_level >= 4) {
                        printf("\tif (pc & 1) {\n");
                        printf("\t\tm68k_areg(regs, 7) -= 6;\n");
-                       printf("\t\texception3i (0x%04X, pc);\n", opcode);
+                       printf("\t\texception3i(0x%04X, pc);\n", opcode);
                        write_return_cycles("\t\t", 0);
                        printf("\t}\n");
                }
@@ -5909,8 +6067,11 @@ static void gen_opcode (unsigned int opcode)
                if (cpu_level < 4) {
                        printf("\tif (%s & 1) {\n", getpc);
                        printf("\t\tuaecptr faultpc = %s;\n", getpc);
+                       if (cpu_level == 1) {
+                               dummy_prefetch(NULL, NULL);
+                       }
                        setpc("oldpc");
-                       printf("\t\texception3i (0x%04X, faultpc);\n", opcode);
+                       printf("\t\texception3i(0x%04X, faultpc);\n", opcode);
                        write_return_cycles("\t\t", 0);
                        printf("\t}\n");
                }
@@ -5934,7 +6095,10 @@ static void gen_opcode (unsigned int opcode)
                        printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
                        if (using_exception_3 && cpu_level <= 1) {
                                printf("\tif (srca & 1) {\n");
-                               printf("\t\texception3i (opcode, srca);\n");
+                               if (curi->smode >= Ad16 && cpu_level == 1 && using_prefetch) {
+                                       dummy_prefetch("srca", NULL);
+                               }
+                               printf("\t\texception3i(opcode, srca);\n");
                                write_return_cycles("\t\t", 0);
                                printf("\t}\n");
                        }
@@ -5957,7 +6121,7 @@ static void gen_opcode (unsigned int opcode)
                                        printf("\tm68k_areg(regs, 7) -= 4;\n");
                                if (using_exception_3 && cpu_level >= 2) {
                                        printf("\tif (%s & 1) {\n", getpc);
-                                       printf("\t\texception3i (opcode, %s);\n", getpc);
+                                       printf("\t\texception3i(opcode, %s);\n", getpc);
                                        write_return_cycles("\t\t", 0);
                                        printf("\t}\n");
                                }
@@ -5995,7 +6159,7 @@ static void gen_opcode (unsigned int opcode)
                                int sp = (curi->smode == Ad16 || curi->smode == absw || curi->smode == absl || curi->smode == PC16 || curi->smode == Ad8r || curi->smode == PC8r) ? -1 : 0;
                                irc2ir();
                                copy_opcode();
-                               if (sp < 0)
+                               if (sp < 0 && cpu_level == 0)
                                        printf("\tif(regs.t1) opcode |= 0x10000;\n");
                                printf("\t%s(%d);\n", prefetch_word, 2);
                                check_prefetch_bus_error(-2, sp);
@@ -6015,7 +6179,10 @@ static void gen_opcode (unsigned int opcode)
                genamode (curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA|GF_NOREFILL);
                if (using_exception_3) {
                        printf("\tif (srca & 1) {\n");
-                       printf("\t\texception3i (opcode, srca);\n");
+                       if (curi->smode >= Ad16 && cpu_level == 1 && using_prefetch) {
+                               dummy_prefetch("srca", NULL);
+                       }
+                       printf("\t\texception3i(opcode, srca);\n");
                        write_return_cycles("\t\t", 0);
                        printf("\t}\n");
                }
@@ -6032,7 +6199,7 @@ static void gen_opcode (unsigned int opcode)
                        printf("\t%s(%d);\n", prefetch_word, 2);
                        int sp = (curi->smode == Ad16 || curi->smode == absw || curi->smode == absl || curi->smode == PC16 || curi->smode == Ad8r || curi->smode == PC8r) ? -1 : 0;
                        copy_opcode();
-                       if (sp < 0)
+                       if (sp < 0 && cpu_level == 0)
                                printf("\tif(regs.t1) opcode |= 0x10000;\n");
                        check_prefetch_bus_error(-2, sp);
                        did_prefetch = 1;
@@ -6079,9 +6246,7 @@ static void gen_opcode (unsigned int opcode)
                if (using_exception_3 && cpu_level == 1) {
                        // 68010 TODO: looks like prefetches are done first and stack writes last
                        printf("\tif (s & 1) {\n");
-                       setpc("(oldpc + s) & ~1");
-                       printf("\t%s(0);\n", prefetch_word);
-                       setpc("oldpc");
+                       dummy_prefetch("(oldpc + s) & ~1", "oldpc");
                        printf("\t\texception3b(opcode, oldpc + s, false, true, %s);\n", getpc);
                        write_return_cycles("\t\t", 0);
                        printf("\t}\n");
@@ -6169,8 +6334,7 @@ static void gen_opcode (unsigned int opcode)
                        if (cpu_level == 1) {
                                printf("\t\tuaecptr oldpc = %s;\n", getpc);
                                incpc("((uae_s32)src + 2) & ~1");
-                               printf("\t%s(0);\n", prefetch_word);
-                               setpc("oldpc");
+                               dummy_prefetch(NULL, "oldpc");
                        }
                        printf("\t\t\texception3i(opcode, %s + 2 + (uae_s32)src);\n", getpc);
                        write_return_cycles("\t\t\t", 0);
@@ -6256,7 +6420,7 @@ bccl_not68020:
                addcycles000 (2);
                if (using_exception_3 && cpu_level >= 4) {
                        printf("\tif (offs & 1) {\n");
-                       printf("\t\t\texception3i (opcode, oldpc + (uae_s32)offs + 2);\n");
+                       printf("\t\t\texception3i(opcode, oldpc + (uae_s32)offs + 2);\n");
                        write_return_cycles("\t\t", 0);
                        printf("\t\t}\n");
                }
@@ -6264,14 +6428,19 @@ bccl_not68020:
                printf("\tif (!cctrue(%d)) {\n", curi->cc);
                printf("\t");
                incpc ("(uae_s32)offs + 2");
-               if (cpu_level >= 2 && cpu_level < 4)
+               if (cpu_level >= 2 && cpu_level < 4) {
                        genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src");
+               }
                printf("\t");
                if (using_exception_3 && cpu_level < 4) {
                        printf("\tif (offs & 1) {\n");
-                       printf("\t\t\texception3i (opcode, %s);\n", getpc);
+                       if (cpu_level == 1) {
+                               printf("\t\t\t%s(%d);\n", prefetch_word, -1);
+                       }
+                       printf("\t\t\texception3i(opcode, %s);\n", getpc);
                        write_return_cycles("\t\t", 0);
                        printf("\t\t}\n");
+                       
                }
                // 68010 loop mode handling
                if (cpu_level == 1) {
@@ -6311,7 +6480,9 @@ bccl_not68020:
 
                if (using_prefetch || using_ce) {
                        copy_opcode();
-                       printf("\tif(regs.t1) opcode |= 0x10000;\n");
+                       if (cpu_level == 0) {
+                               printf("\tif(regs.t1) opcode |= 0x10000;\n");
+                       }
                        printf("\t%s(%d);\n", prefetch_word, 2);
                        check_prefetch_bus_error(-2, -1);
                        did_prefetch = 1;
@@ -6351,7 +6522,9 @@ bccl_not68020:
                                printf("\tif (!val) {\n");
                                genastore("val", curi->smode, "srcreg", curi->size, "src");
                                printf("\t}\n");
-                               printf("\topcode |= 0x20000;\n");
+                               if (cpu_level == 0) {
+                                       printf("\topcode |= 0x20000;\n");
+                               }
                        }
                        fill_prefetch_next_extra("if (!val)", "\t\tif(!val && regs.t1) opcode |= 0x10000;\n");
                        genastore("val", curi->smode, "srcreg", curi->size, "src");
index f4b0d3daf6c114afd9467b21e983c1a20e396555..0a9647f2bd5706406d737a749414be49819a631f 100644 (file)
@@ -333,29 +333,33 @@ STATIC_INLINE void m68k_do_rts_ce030 (void)
 STATIC_INLINE uae_u32 get_word_000_prefetch(int o)
 {
        uae_u32 v = regs.irc;
-       regs.irc = regs.db = get_wordi (m68k_getpci () + o);
+       regs.irc = regs.read_buffer = regs.db = get_wordi (m68k_getpci () + o);
        return v;
 }
 STATIC_INLINE uae_u32 get_byte_000(uaecptr addr)
 {
        uae_u32 v = get_byte (addr);
        regs.db = (v << 8) | v;
+       regs.read_buffer = v;
        return v;
 }
 STATIC_INLINE uae_u32 get_word_000(uaecptr addr)
 {
        uae_u32 v = get_word (addr);
        regs.db = v;
+       regs.read_buffer = v;
        return v;
 }
 STATIC_INLINE void put_byte_000(uaecptr addr, uae_u32 v)
 {
        regs.db = (v << 8) | v;
+       regs.write_buffer = v;
        put_byte (addr, v);
 }
 STATIC_INLINE void put_word_000(uaecptr addr, uae_u32 v)
 {
        regs.db = v;
+       regs.write_buffer = v;
        put_word (addr, v);
 }
 #endif
index ff9448260bc7a59ae5ad8ab83738acdd31083813..4fef3385e0b2241540e8102140acd869fd7e07f2 100644 (file)
@@ -178,13 +178,13 @@ struct regstruct
        uae_u32 instruction_pc_user_exception;
        uae_u32 trace_pc;
 
-       uae_u16 irc, ir, ird, db;
+       uae_u16 irc, ir, ird;
        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;
+       uae_u16 db, write_buffer, read_buffer;
        bool loop_mode;
 
        uaecptr usp, isp, msp;
@@ -287,6 +287,7 @@ struct cputracestruct
        int pipeline_pos;
        int pipeline_r8[2];
        int pipeline_stop;
+       uae_u16 read_buffer, write_buffer;
 
        uae_u32 startcycles;
        int needendcycles;
index 97e597ba64029124170a84cfa7ee4a197e70b04c..05dbe4640ad208cfa6de5c02b06e825eccad109b 100644 (file)
@@ -4454,6 +4454,8 @@ static void m68k_run_1_ce (void)
                                        r->isp = cputrace.isp;
                                        r->intmask = cputrace.intmask;
                                        r->stopped = cputrace.stopped;
+                                       r->read_buffer = cputrace.read_buffer;
+                                       r->write_buffer = cputrace.write_buffer;
                                        m68k_setpc (cputrace.pc);
                                        if (!r->stopped) {
                                                if (cputrace.state > 1) {
@@ -4492,6 +4494,8 @@ static void m68k_run_1_ce (void)
                                        cputrace.isp = r->isp;
                                        cputrace.intmask = r->intmask;
                                        cputrace.stopped = r->stopped;
+                                       cputrace.read_buffer = r->read_buffer;
+                                       cputrace.write_buffer = r->write_buffer;
                                        cputrace.state = 1;
                                        cputrace.pc = m68k_getpc ();
                                        cputrace.startcycles = get_cycles ();
@@ -6243,7 +6247,6 @@ 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 ();
@@ -6406,6 +6409,13 @@ uae_u8 *restore_cpu (uae_u8 *src)
                regs.pipeline_stop = restore_u16();
        }
 
+       if (flags & 0x2000000 && currprefs.cpu_model <= 68010) {
+               restore_u32();
+               regs.ird = restore_u16();
+               regs.read_buffer = restore_u16();
+               regs.write_buffer = restore_u16();
+       }
+
        m68k_reset_sr();
 
        write_log (_T("CPU: %d%s%03d, PC=%08X\n"),
@@ -6510,6 +6520,8 @@ uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
        }
 
        save_u16(cputrace.ird);
+       save_u16(cputrace.read_buffer);
+       save_u16(cputrace.writecounter);
 
        *len = dst - dstbak;
        cputrace.needendcycles = 1;
@@ -6600,6 +6612,8 @@ uae_u8 *restore_cpu_trace (uae_u8 *src)
                        }
                        if (v & 64) {
                                cputrace.ird = restore_u16();
+                               cputrace.read_buffer = restore_u16();
+                               cputrace.write_buffer = restore_u16();
                        }
                }
        }
@@ -6686,7 +6700,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                dstbak = dst = xmalloc (uae_u8, 1000 + 30000);
        model = currprefs.cpu_model;
        save_u32 (model);                                       /* MODEL */
-       save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 | 0x4000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
+       save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 | 0x4000000 | 0x2000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
        for (int i = 0;i < 15; i++)
                save_u32 (regs.regs[i]);                /* D0-D7 A0-A6 */
        save_u32 (m68k_getpc ());                       /* PC */
@@ -6696,7 +6710,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) | (regs.ird << 16)); /* flags + ird */
+       save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */
        if (model >= 68010) {
                save_u32 (regs.dfc);                    /* DFC */
                save_u32 (regs.sfc);                    /* SFC */
@@ -6824,6 +6838,12 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                save_u16(regs.pipeline_r8[1]);
                save_u16(regs.pipeline_stop);
        }
+       if (currprefs.cpu_model <= 68010) {
+               save_u32(0);
+               save_u16(regs.ird);
+               save_u16(regs.read_buffer);
+               save_u16(regs.write_buffer);
+       }
        *len = dst - dstbak;
        return dstbak;
 }
@@ -9161,6 +9181,7 @@ void fill_prefetch (void)
                regs.ir = x_get_word (pc);
                regs.ird = regs.ir;
                regs.irc = x_get_word (pc + 2);
+               regs.read_buffer = regs.irc;
        }
 }