]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
More 68040/060 fixes. (Undefined fields in some instructions, MUL.L/DIV.L -(an)/...
authorToni Wilen <twilen@winuae.net>
Fri, 23 Aug 2019 19:39:07 +0000 (22:39 +0300)
committerToni Wilen <twilen@winuae.net>
Fri, 23 Aug 2019 19:39:07 +0000 (22:39 +0300)
cputest.cpp
gencpu.cpp
include/newcpu.h
newcpu.cpp
newcpu_common.cpp

index 173a18c5bd3b4fd2b37ed54d7af97d161f4ecdf4..921b851cde3f2e9bd54db2053deaf2cb29f81597 100644 (file)
@@ -40,6 +40,7 @@ const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
 int movem_index1[256];
 int movem_index2[256];
 int movem_next[256];
+struct mmufixup mmufixup[2];
 cpuop_func *cpufunctbl[65536];
 struct cputbl_data
 {
@@ -1558,15 +1559,20 @@ static void handle_specials_extra(uae_u16 opcode, uaecptr pc, struct instr *dp)
        // cas undocumented (marked as zero in document) fields do something weird, for example
        // setting bit 9 will make "Du" address register but results are not correct.
        // so lets make sure unused zero bits are zeroed.
-       if (dp->mnemo == i_CAS) {
+       switch (dp->mnemo)
+       {
+       case i_CAS:
+       {
                uae_u16 extra = get_word_test(opcode_memory_start + 2);
                uae_u16 extra2 = extra;
                extra &= (7 << 6) | (7 << 0);
                if (extra != extra2) {
                        put_word_test(opcode_memory_start + 2, extra);
                }
+               break;
        }
-       if (dp->mnemo == i_CAS2) {
+       case i_CAS2:
+       {
                uae_u16 extra = get_word_test(opcode_memory_start + 2);
                uae_u16 extra2 = extra;
                extra &= (7 << 6) | (7 << 0) | (15 << 12);
@@ -1579,14 +1585,49 @@ static void handle_specials_extra(uae_u16 opcode, uaecptr pc, struct instr *dp)
                if (extra != extra2) {
                        put_word_test(opcode_memory_start + 4, extra);
                }
+               break;
        }
-       if (dp->mnemo == i_CHK2) {
+       case i_CHK2:
+       {
                uae_u16 extra = get_word_test(opcode_memory_start + 2);
                uae_u16 extra2 = extra;
                extra &= (15 << 12);
                if (extra != extra2) {
                        put_word_test(opcode_memory_start + 2, extra);
                }
+               break;
+       }
+       case i_BFINS:
+       case i_BFFFO:
+       case i_BFEXTS:
+       case i_BFEXTU:
+       {
+               if (cpu_lvl >= 4) {
+                       // 68040+ and extra word bit 15 not zero (hidden A/D field):
+                       // REGISTER field becomes address register in some internal
+                       // operations, results are also wrong. So clear it here..
+                       uae_u16 extra = get_word_test(opcode_memory_start + 2);
+                       if (extra & 0x8000) {
+                               extra &= ~0x8000;
+                               put_word_test(opcode_memory_start + 2, extra);
+                       }
+               }
+               break;
+       }
+       case i_DIVL:
+       case i_MULL:
+       {
+               if (cpu_lvl >= 4) {
+                       // same as BF instructions but also other bits need clearing
+                       // or results are unexplained..
+                       uae_u16 extra = get_word_test(opcode_memory_start + 2);
+                       if (extra & 0x83f8) {
+                               extra &= ~0x83f8;
+                               put_word_test(opcode_memory_start + 2, extra);
+                       }
+               }
+               break;
+       }
        }
 }
 
@@ -1662,6 +1703,8 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
        // execute instruction
        SPCFLAG_TRACE = 0;
        SPCFLAG_DOTRACE = 0;
+       mmufixup[0].reg = -1;
+       mmufixup[1].reg = -1;
 
        MakeFromSR();
 
index 4cdb9944922eb7fa88d9300bd2c37dda5a833976..8d7ed33d4e5fe4dcb51986b9683865f5e7ade09b 100644 (file)
@@ -48,6 +48,7 @@ static int using_waitstates;
 static int using_simple_cycles;
 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_cycles_ce020;
@@ -861,11 +862,28 @@ static void sync_m68k_pc_noreset (void)
        m68k_pc_offset = m68k_pc_offset_old;
 }
 
-static void addmmufixup (const char *reg)
+static bool needmmufixup(void)
 {
+       if (need_special_fixup) {
+               // need to restore -(an)/(an)+ if unimplemented
+               switch (g_instr->mnemo)
+               {
+               case i_MULL:
+               case i_DIVL:
+               case i_CAS:
+                       return true;
+               }
+       }
        if (!using_mmu)
-               return;
+               return false;
        if (using_mmu == 68040 && (mmufixupstate || mmufixupcnt > 0))
+               return false;
+       return true;
+}
+
+static void addmmufixup (const char *reg)
+{
+       if (!needmmufixup())
                return;
        printf ("\tmmufixup[%d].reg = %s;\n", mmufixupcnt, reg);
        printf ("\tmmufixup[%d].value = m68k_areg (regs, %s);\n", mmufixupcnt, reg);
@@ -5450,8 +5468,8 @@ bccl_not68020:
                        genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_LRMW);
                        if (cpu_level == 5 && curi->size > 0) {
                                printf ("\tif ((dsta & %d) && currprefs.int_no_unimplemented && get_cpu_model () == 68060) {\n", curi->size == 1 ? 1 : 3);
-                               if (curi->dmode == Aipi || curi->dmode == Apdi)
-                                       printf ("\t\tm68k_areg (regs, dstreg) %c= %d;\n", curi->dmode == Aipi ? '-' : '+', 1 << curi->size);
+                               if (mmufixupcnt)
+                                       printf("\t\tcpu_restore_fixup();\n");
                                sync_m68k_pc_noreset ();
                                printf ("\t\top_unimpl (opcode);\n");
                                printf ("\t\tgoto %s;\n", endlabelstr);
@@ -5608,14 +5626,22 @@ bccl_not68020:
                genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
                genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
                sync_m68k_pc ();
-               printf ("\tif (!m68k_divl(opcode, dst, extra)) goto %s;\n", endlabelstr);
+               printf("\tif (!m68k_divl(opcode, dst, extra)) {\n");
+               if (mmufixupcnt)
+                       printf("\t\tcpu_restore_fixup();\n");
+               printf("\t\tgoto %s;\n", endlabelstr);
+               printf("\t}\n");
                need_endlabel = 1;
                break;
        case i_MULL:
                genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
                genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
                sync_m68k_pc ();
-               printf ("\tif (!m68k_mull(opcode, dst, extra)) goto %s;\n", endlabelstr);
+               printf("\tif (!m68k_mull(opcode, dst, extra)) {\n");
+               if (mmufixupcnt)
+                       printf("\t\tcpu_restore_fixup();\n");
+               printf("\t\tgoto %s;\n", endlabelstr);
+               printf("\t}\n");
                need_endlabel = 1;
                break;
        case i_BFTST:
@@ -6404,6 +6430,7 @@ static void generate_cpu_test(int mode)
                cpu_level = 5;
                using_prefetch = 0;
                using_simple_cycles = 0;
+               need_special_fixup = 1;
        }
 
        read_counts();
@@ -6466,6 +6493,7 @@ static void generate_cpu (int id, int mode)
        using_simple_cycles = 0;
        using_indirect = 0;
        cpu_generic = false;
+       need_special_fixup = 0;
 
        if (id == 11 || id == 12) { // 11 = 68010 prefetch, 12 = 68000 prefetch
                cpu_level = id == 11 ? 1 : 0;
@@ -6572,6 +6600,7 @@ static void generate_cpu (int id, int mode)
        } else if (id < 6) {
                cpu_level = 5 - (id - 0); // "generic"
                cpu_generic = true;
+               need_special_fixup = 1;
        } else if (id >= 40 && id < 46) {
                cpu_level = 5 - (id - 40); // "generic" + direct
                cpu_generic = true;
@@ -6584,6 +6613,7 @@ static void generate_cpu (int id, int mode)
        } else if (id >= 50 && id < 56) {
                cpu_level = 5 - (id - 50); // "generic" + indirect
                cpu_generic = true;
+               need_special_fixup = 1;
                if (id == 50) {
                        read_counts();
                        for (rp = 0; rp < nr_cpuop_funcs; rp++)
index ecd331c0bb5a82fa0d5d4f74e74008d5f0a2171a..71757ef781010ad37f90f653a3c69a7e369557cd 100644 (file)
@@ -691,6 +691,7 @@ extern void Exception_build_stack_frame_common(uae_u32 oldpc, uae_u32 currpc, ua
 extern void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format);
 extern void Exception_build_68000_address_error_stack_frame(uae_u16 mode, uae_u16 opcode, uaecptr fault_addr, uaecptr pc);
 extern uae_u32 exception_pc(int nr);
+extern void cpu_restore_fixup(void);
 
 void ccr_68000_long_move_ae_LZN(uae_s32 src);
 void ccr_68000_long_move_ae_LN(uae_s32 src);
index 4f61b88a84f5e2cba3bfd438d72cd85ed8f56d84..55d8f85ed0253f6bc6efa0b959b92665917808a3 100644 (file)
@@ -5080,16 +5080,7 @@ static void m68k_run_mmu060 (void)
                        m68k_setpci (regs.instruction_pc);
                        regflags.cznv = f.cznv;
                        regflags.x = f.x;
-
-                       if (mmufixup[0].reg >= 0) {
-                               m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
-                               mmufixup[0].reg = -1;
-                       }
-                       if (mmufixup[1].reg >= 0) {
-                               m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
-                               mmufixup[1].reg = -1;
-                       }
-
+                       cpu_restore_fixup();
                        TRY (prb2) {
                                Exception (prb);
                        } CATCH (prb2) {
@@ -5140,12 +5131,7 @@ static void m68k_run_mmu040 (void)
                                regflags.x = f.x;
                                m68k_setpci (regs.instruction_pc);
                        }
-
-                       if (mmufixup[0].reg >= 0) {
-                               m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
-                               mmufixup[0].reg = -1;
-                       }
-
+                       cpu_restore_fixup();
                        TRY (prb2) {
                                Exception (prb);
                        } CATCH (prb2) {
@@ -5275,15 +5261,7 @@ insretry:
                        } else {
                                regflags.cznv = f.cznv;
                                regflags.x = f.x;
-
-                               if (mmufixup[0].reg >= 0) {
-                                       m68k_areg(regs, mmufixup[0].reg) = mmufixup[0].value;
-                                       mmufixup[0].reg = -1;
-                               }
-                               if (mmufixup[1].reg >= 0) {
-                                       m68k_areg(regs, mmufixup[1].reg) = mmufixup[1].value;
-                                       mmufixup[1].reg = -1;
-                               }
+                               cpu_restore_fixup();
                        }
 
                        m68k_setpci (regs.instruction_pc);
index 7befe6227c4bdda6c974a400b1ce452abe246701..3187cd2174fd14954e0e1f077158a92793b0ca5f 100644 (file)
@@ -860,12 +860,13 @@ void setdivsoverflowflags(uae_s32 dividend, uae_s16 divisor)
  *
  * 68000: CV=0. Z: dst==0. N: dst < 0. !N: dst > src.
  * 68020: Z: dst==0. N: dst < 0. V: src-dst overflow. C: if dst < 0: (dst > src || src >= 0), if dst > src: (src >= 0).
+ * 68040: N=0. If exception: N=dst < 0
  *
  */
 void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
 {
-       CLEAR_CZNV();
        if (currprefs.cpu_model < 68020) {
+               CLEAR_CZNV();
                if (dst == 0)
                        SET_ZFLG(1);
                if (dst < 0)
@@ -873,6 +874,7 @@ void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
                else if (dst > src)
                        SET_NFLG(0);
        } else if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
+               CLEAR_CZNV();
                if (dst == 0)
                        SET_ZFLG(1);
                SET_NFLG(dst < 0);
@@ -896,6 +898,11 @@ void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
                                SET_CFLG(src >= 0);
                        }
                }
+       } else {
+               SET_NFLG(0);
+               if (dst < 0 || dst > src) {
+                       SET_NFLG(dst < 0);
+               }
        }
 }
 
@@ -963,6 +970,9 @@ bool m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
                return false;
        }
        if (src == 0) {
+               if (currprefs.cpu_model == 68060) {
+                       SET_CFLG(0);
+               }
                Exception_cpu(5);
                return false;
        }
@@ -1473,6 +1483,18 @@ void Exception_build_68000_address_error_stack_frame(uae_u16 mode, uae_u16 opcod
        x_put_long(m68k_areg(regs, 7) + 10, pc);
 }
 
+void cpu_restore_fixup(void)
+{
+       if (mmufixup[0].reg >= 0) {
+               m68k_areg(regs, mmufixup[0].reg) = mmufixup[0].value;
+               mmufixup[0].reg = -1;
+       }
+       if (mmufixup[1].reg >= 0) {
+               m68k_areg(regs, mmufixup[1].reg) = mmufixup[1].value;
+               mmufixup[1].reg = -1;
+       }
+}
+
 // Low word: Z and N
 void ccr_68000_long_move_ae_LZN(uae_s32 src)
 {