]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68040 specific CPU tester fixes.
authorToni Wilen <twilen@winuae.net>
Sat, 24 Aug 2019 19:02:43 +0000 (22:02 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 24 Aug 2019 19:02:43 +0000 (22:02 +0300)
cputest.cpp
gencpu.cpp
include/newcpu.h
newcpu_common.cpp

index 921b851cde3f2e9bd54db2053deaf2cb29f81597..03afa1946937ecdddad782f5869810e4a373598a 100644 (file)
@@ -733,7 +733,7 @@ static void doexcstack(void)
                }
        } else {
                if (test_exception == 3) {
-                       if (currprefs.cpu_model == 68060)
+                       if (currprefs.cpu_model >= 68040)
                                test_exception_addr &= ~1;
                        Exception_build_stack_frame(test_exception_addr, regs.pc, 0, 3, 0x02);
                } else {
@@ -1692,9 +1692,9 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
 {
        uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
        uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
-       if (opc == 0xf603
-               && opw1 == 0x6884
-               && opw2 == 0x618d
+       if (opc == 0x4c40 
+               && opw1 == 0x2406
+//             && opw2 == 0x618d
                )
                printf("");
        if (regs.sr & 0x2000)
index 8d7ed33d4e5fe4dcb51986b9683865f5e7ade09b..6b8410bd7da7bfd83d84ce1306a1ffc4218d4d1e 100644 (file)
@@ -1343,6 +1343,15 @@ static int gence020cycles_jea (instr *curi, amodes mode)
        return oph;
 }
 
+// 68020-30 needs different implementation than 68040/060
+static void next_level_040_to_030(void)
+{
+       if (cpu_level >= 4) {
+               if (next_cpu_level < 4)
+                       next_cpu_level = 4 - 1;
+       }
+}
+
 static void next_level_000 (void)
 {
        if (next_cpu_level < 0)
@@ -4360,31 +4369,44 @@ static void gen_opcode (unsigned int opcode)
                fill_prefetch_full ();
            need_endlabel = 1;
                branch_inst = 1;
-               if (cpu_level >= 4) {
-                       if (next_cpu_level < 4)
-                               next_cpu_level = 4 - 1;
-               }
+               next_level_040_to_030();
                break;
        case i_LINK:
                // ce confirmed
+               // 68040 uses different order than other CPU models.
                if (using_mmu) {
-                       addmmufixup ("srcreg");
-                       genamode (NULL, curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
-                       genamode (NULL, Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, 0);
-                       genamode (NULL, curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
-                       genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
-                       printf ("\tm68k_areg(regs, 7) += offs;\n");
-                       genastore ("src", Apdi, "7", sz_long, "old");
+                       addmmufixup("srcreg");
+                       genamode(NULL, curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
+                       if (cpu_level == 4) {
+                               genamode(NULL, Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, 0);
+                               genastore("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
+                               genamode(NULL, curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
+                       } else {
+                               genamode(NULL, curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
+                               genamode(NULL, Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, 0);
+                               genastore("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
+                       }
+                       printf("\tm68k_areg(regs, 7) += offs;\n");
+                       genastore("src", Apdi, "7", sz_long, "old");
                } else {
-                       addop_ce020 (curi, 0);
-                       genamode (NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA);
-                       // smode must be first in case it is A7.
-                       genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA);
-                       genamode (NULL, curi->dmode, "dstreg", curi->size, "offs", 1, 0, 0);
-                       genastore ("src", Apdi, "7", sz_long, "old");
-                       genastore ("m68k_areg (regs, 7)", curi->smode, "srcreg", sz_long, "src");
-                       printf ("\tm68k_areg (regs, 7) += offs;\n");
-                       fill_prefetch_next ();
+                       addop_ce020(curi, 0);
+                       // smode must be first in case it is A7. Except if 68040!
+                       if (cpu_level == 4) {
+                               genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA);
+                               genamode(NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA);
+                       } else {
+                               genamode(NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA);
+                               genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA);
+                       }
+                       genamode(NULL, curi->dmode, "dstreg", curi->size, "offs", 1, 0, 0);
+                       genastore("src", Apdi, "7", sz_long, "old");
+                       genastore("m68k_areg (regs, 7)", curi->smode, "srcreg", sz_long, "src");
+                       printf("\tm68k_areg (regs, 7) += offs;\n");
+                       fill_prefetch_next();
+                       if (cpu_level >= 5) {
+                               if (next_cpu_level < 5)
+                                       next_cpu_level = 5 - 1;
+                       }
                }
                break;
        case i_UNLK:
@@ -4446,10 +4468,7 @@ static void gen_opcode (unsigned int opcode)
                fill_prefetch_full ();
            need_endlabel = 1;
                branch_inst = 1;
-               if (cpu_level >= 4) {
-                       if (next_cpu_level < 4)
-                               next_cpu_level = 4 - 1;
-               }
+               next_level_040_to_030();
                break;
        case i_TRAPV:
                sync_m68k_pc ();
@@ -4489,10 +4508,7 @@ static void gen_opcode (unsigned int opcode)
            need_endlabel = 1;
                branch_inst = 1;
                tail_ce020_done = true;
-               if (cpu_level >= 4) {
-                       if (next_cpu_level < 4)
-                               next_cpu_level = 4 - 1;
-               }
+               next_level_040_to_030();
                break;
        case i_JSR:
                // possible idle cycle, prefetch from new address, stack high return addr, stack low, prefetch
@@ -4557,10 +4573,7 @@ static void gen_opcode (unsigned int opcode)
                fill_prefetch_full_020 ();
                fill_prefetch_next ();
                branch_inst = 1;
-               if (cpu_level >= 4) {
-                       if (next_cpu_level < 4)
-                               next_cpu_level = 4 - 1;
-               }
+               next_level_040_to_030();
                break;
        case i_JMP:
                no_prefetch_ce020 = true;
@@ -4725,10 +4738,7 @@ static void gen_opcode (unsigned int opcode)
                insn_n_cycles = curi->size == sz_byte ? 8 : 12;
                branch_inst = 1;
 bccl_not68020:
-               if (cpu_level >= 4) {
-                       if (next_cpu_level < 4)
-                               next_cpu_level = 4 - 1;
-               }
+               next_level_040_to_030();
                break;
        case i_LEA:
                if (curi->smode == Ad8r || curi->smode == PC8r)
@@ -4812,10 +4822,7 @@ bccl_not68020:
                insn_n_cycles = 12;
                need_endlabel = 1;
                branch_inst = 1;
-               if (cpu_level >= 4) {
-                       if (next_cpu_level < 4)
-                               next_cpu_level = 4 - 1;
-               }
+               next_level_040_to_030();
                break;
        case i_Scc:
                // confirmed
@@ -4838,78 +4845,78 @@ bccl_not68020:
                genamodedual (curi,
                        curi->smode, "srcreg", sz_word, "src", 1, 0,
                        curi->dmode, "dstreg", sz_long, "dst", 1, 0);
-               printf ("\tCLEAR_CZNV ();\n");
-               printf ("\tif (src == 0) {\n");
-               printf ("\t\tdivbyzero_special (0, dst);\n");
-               incpc ("%d", m68k_pc_offset);
-               printf ("\t\tException_cpu(5);\n");
-               printf ("\t\tgoto %s;\n", endlabelstr);
-               printf ("\t} else {\n");
-               printf ("\t\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
-               printf ("\t\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
+               printf("\tif (src == 0) {\n");
+               printf("\t\tdivbyzero_special(0, dst);\n");
+               incpc("%d", m68k_pc_offset);
+               printf("\t\tException_cpu(5);\n");
+               printf("\t\tgoto %s;\n", endlabelstr);
+               printf("\t}\n");
+               printf("\tsetdivuflags(false, (uae_u32)dst, (uae_u16)src);\n");
+               printf("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
+               printf("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
                if (using_ce) {
-                       start_brace ();
-                       printf ("\t\tint cycles = (getDivu68kCycles((uae_u32)dst, (uae_u16)src)) - 4;\n");
-                       addcycles000_3 ("\t\t");
+                       start_brace();
+                       printf("\t\tint cycles = (getDivu68kCycles((uae_u32)dst, (uae_u16)src)) - 4;\n");
+                       addcycles000_3("\t\t");
                }
                addcycles000_nonces("\t\t", "(getDivu68kCycles((uae_u32)dst, (uae_u16)src)) - 4");
-               fill_prefetch_next ();
-               /* The N flag appears to be set each time there is an overflow.
-                * Weird. but 68020 only sets N when dst is negative.. */
-               printf ("\t\tif (newv > 0xffff) {\n");
-               printf ("\t\t\tsetdivuoverflowflags((uae_u32)dst, (uae_u16)src);\n");
-               printf ("\t\t} else {\n");
-               printf ("\t\t"); genflags (flag_logical, sz_word, "newv", "", "");
-               printf ("\t\t\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
-               printf ("\t\t"); genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
-               printf ("\t\t}\n");
-               sync_m68k_pc ();
-               printf ("\t}\n");
+               fill_prefetch_next();
+               printf("\t\tif (newv > 0xffff) {\n");
+               printf("\t\t\tsetdivuflags(true, (uae_u32)dst, (uae_u16)src);\n");
+               printf("\t\t} else {\n");
+               printf("\t\t");
+               genflags (flag_logical, sz_word, "newv", "", "");
+               printf("\t\t\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
+               printf("\t\t");
+               genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+               printf("\t\t}\n");
+               sync_m68k_pc();
                count_ncycles++;
                insn_n_cycles += 136 - (136 - 76) / 2; /* average */
                need_endlabel = 1;
                tail_ce020_done = false;
-               returntail (false);
+               returntail(false);
                break;
        case i_DIVS:
                tail_ce020_done = true;
-               genamodedual (curi,
+               genamodedual(curi,
                        curi->smode, "srcreg", sz_word, "src", 1, 0,
                        curi->dmode, "dstreg", sz_long, "dst", 1, 0);
-               printf ("\tif (src == 0) {\n");
-               printf ("\t\tdivbyzero_special (1, dst);\n");
-               incpc ("%d", m68k_pc_offset);
-               printf ("\t\tException_cpu(5);\n");
-               printf ("\t\tgoto %s;\n", endlabelstr);
-               printf ("\t}\n");
-               printf ("\tCLEAR_CZNV ();\n");
+               printf("\tif (src == 0) {\n");
+               printf("\t\tdivbyzero_special (1, dst);\n");
+               incpc("%d", m68k_pc_offset);
+               printf("\t\tException_cpu(5);\n");
+               printf("\t\tgoto %s;\n", endlabelstr);
+               printf("\t}\n");
+               printf("\tsetdivsflags(false, (uae_s32)dst, (uae_s16)src);\n");
                if (using_ce) {
-                       start_brace ();
-                       printf ("\t\tint cycles = (getDivs68kCycles((uae_s32)dst, (uae_s16)src)) - 4;\n");
-                       addcycles000_3 ("\t\t");
+                       start_brace();
+                       printf("\t\tint cycles = (getDivs68kCycles((uae_s32)dst, (uae_s16)src)) - 4;\n");
+                       addcycles000_3("\t\t");
                }
                addcycles000_nonces("\t\t", "(getDivs68kCycles((uae_s32)dst, (uae_s16)src)) - 4");
                fill_prefetch_next ();
-               printf ("\tif (dst == 0x80000000 && src == -1) {\n");
-               printf ("\t\tsetdivsoverflowflags((uae_s32)dst, (uae_s16)src);\n");
-               printf ("\t} else {\n");
-               printf ("\t\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
-               printf ("\t\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
-               printf ("\t\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) {\n");
-               printf ("\t\t\tsetdivsoverflowflags((uae_s32)dst, (uae_s16)src);\n");
-               printf ("\t\t} else {\n");
-               printf ("\t\t\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
-               genflags (flag_logical, sz_word, "newv", "", "");
-               printf ("\t\t\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
-               printf ("\t\t"); genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
-               printf ("\t\t}\n");
-               printf ("\t}\n");
-               sync_m68k_pc ();
+               printf("\tif (dst == 0x80000000 && src == -1) {\n");
+               printf("\t\tsetdivsflags(true, (uae_s32)dst, (uae_s16)src);\n");
+               printf("\t} else {\n");
+               printf("\t\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
+               printf("\t\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
+               printf("\t\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) {\n");
+               printf("\t\t\tsetdivsflags(true, (uae_s32)dst, (uae_s16)src);\n");
+               printf("\t\t} else {\n");
+               printf("\t\t\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
+               genflags(flag_logical, sz_word, "newv", "", "");
+               printf("\t\t\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
+               printf("\t\t");
+               genastore("newv", curi->dmode, "dstreg", sz_long, "dst");
+               printf("\t\t}\n");
+               printf("\t}\n");
+               sync_m68k_pc();
                count_ncycles++;
                insn_n_cycles += 156 - (156 - 120) / 2; /* average */
                need_endlabel = 1;
                tail_ce020_done = false;
-               returntail (false);
+               returntail(false);
                break;
        case i_MULU:
                genamodedual (curi,
@@ -5513,40 +5520,53 @@ bccl_not68020:
                }
                break;
        case i_CAS2:
-               genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, GF_LRMW);
-               printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
-               printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
+               genamode(curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, GF_LRMW);
+               printf("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
+               printf("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
                if (curi->size == sz_word) {
                        int old_brace_level = n_braces;
-                       printf ("\tuae_u16 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcwlrmw, srcwlrmw);
-                       genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1");
-                       printf ("\tif (GET_ZFLG ()) {\n");
-                       genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2");
-                       printf ("\tif (GET_ZFLG ()) {\n");
-                       printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstwlrmw);
-                       printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstwlrmw);
-                       printf ("\t}}\n");
-                       pop_braces (old_brace_level);
-                       printf ("\tif (! GET_ZFLG ()) {\n");
-                       printf ("\tm68k_dreg (regs, (extra >> 0) & 7) = (m68k_dreg (regs, (extra >> 0) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
-                       printf ("\tm68k_dreg (regs, (extra >> 16) & 7) = (m68k_dreg (regs, (extra >> 16) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
+                       printf("\tuae_u16 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcwlrmw, srcwlrmw);
+                       genflags(flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1");
+                       printf("\tif (GET_ZFLG ()) {\n");
+                       genflags(flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2");
+                       printf("\tif (GET_ZFLG ()) {\n");
+                       printf("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstwlrmw);
+                       printf("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstwlrmw);
+                       printf("\t}}\n");
+                       pop_braces(old_brace_level);
+                       printf("\tif (! GET_ZFLG ()) {\n");
+                       if (cpu_level >= 4) {
+                               // 68040: register update order swapped
+                               printf("\tm68k_dreg (regs, (extra >> 16) & 7) = (m68k_dreg (regs, (extra >> 16) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
+                               printf("\tm68k_dreg (regs, (extra >> 0) & 7) = (m68k_dreg (regs, (extra >> 0) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
+                       } else {
+                               printf("\tm68k_dreg (regs, (extra >> 0) & 7) = (m68k_dreg (regs, (extra >> 0) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
+                               printf("\tm68k_dreg (regs, (extra >> 16) & 7) = (m68k_dreg (regs, (extra >> 16) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
+                       }
                        printf ("\t}\n");
                } else {
                        int old_brace_level = n_braces;
-                       printf ("\tuae_u32 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcllrmw, srcllrmw);
-                       genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1");
-                       printf ("\tif (GET_ZFLG ()) {\n");
-                       genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2");
-                       printf ("\tif (GET_ZFLG ()) {\n");
-                       printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstllrmw);
-                       printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstllrmw);
-                       printf ("\t}}\n");
-                       pop_braces (old_brace_level);
-                       printf ("\tif (! GET_ZFLG ()) {\n");
-                       printf ("\tm68k_dreg (regs, (extra >> 0) & 7) = dst2;\n");
-                       printf ("\tm68k_dreg (regs, (extra >> 16) & 7) = dst1;\n");
+                       printf("\tuae_u32 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcllrmw, srcllrmw);
+                       genflags(flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1");
+                       printf("\tif (GET_ZFLG ()) {\n");
+                       genflags(flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2");
+                       printf("\tif (GET_ZFLG ()) {\n");
+                       printf("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstllrmw);
+                       printf("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstllrmw);
+                       printf("\t}}\n");
+                       pop_braces(old_brace_level);
+                       printf("\tif (! GET_ZFLG ()) {\n");
+                       if (cpu_level >= 4) {
+                               // 68040: register update order swapped
+                               printf("\tm68k_dreg (regs, (extra >> 16) & 7) = dst1;\n");
+                               printf("\tm68k_dreg (regs, (extra >> 0) & 7) = dst2;\n");
+                       } else {
+                               printf("\tm68k_dreg (regs, (extra >> 0) & 7) = dst2;\n");
+                               printf("\tm68k_dreg (regs, (extra >> 16) & 7) = dst1;\n");
+                       }
                        printf ("\t}\n");
                }
+               next_level_040_to_030();
                break;
        case i_MOVES: /* ignore DFC and SFC when using_mmu == false */
                {
@@ -5594,11 +5614,8 @@ bccl_not68020:
                                returntail(false);
                                pop_braces (old_brace_level);
                        }
-                       if (cpu_level >= 4) {
-                               if (next_cpu_level < 4)
-                                       next_cpu_level = 4 - 1;
-                       }
-               }
+                       next_level_040_to_030();
+       }
                break;
        case i_BKPT:            /* only needed for hardware emulators */
                sync_m68k_pc ();
index 71757ef781010ad37f90f653a3c69a7e369557cd..83d823c55fdeb137f102aa6841efcb359404359a 100644 (file)
@@ -679,8 +679,8 @@ extern void m68k_dumpcache (bool);
 extern int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor);
 extern int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor);
 extern void divbyzero_special(bool issigned, uae_s32 dst);
-extern void setdivuoverflowflags(uae_u32 dividend, uae_u16 divisor);
-extern void setdivsoverflowflags(uae_s32 dividend, uae_s16 divisor);
+extern void setdivuflags(bool overflow, uae_u32 dividend, uae_u16 divisor);
+extern void setdivsflags(bool overflow, uae_s32 dividend, uae_s16 divisor);
 extern void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size);
 extern void setchk2undefinedflags(uae_u32 lower, uae_u32 upper, uae_u32 val, int size);
 extern void protect_roms (bool);
index 3187cd2174fd14954e0e1f077158a92793b0ca5f..618e0a61b376118df76c34ce8cfede6aec82fe1f 100644 (file)
@@ -769,7 +769,7 @@ int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
 void divbyzero_special (bool issigned, uae_s32 dst)
 {
        if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
-               CLEAR_CZNV ();
+               CLEAR_CZNV();
                if (issigned) {
                        SET_ZFLG(1);
                } else {
@@ -778,9 +778,11 @@ void divbyzero_special (bool issigned, uae_s32 dst)
                                SET_NFLG(1);
                        else if (d == 0)
                                SET_ZFLG(1);
-                       SET_VFLG (1);
+                       SET_VFLG(1);
                }
-       } else if (currprefs.cpu_model >= 68040) {
+       } else if (currprefs.cpu_model == 68040) {
+               SET_CFLG(0);
+       } else if (currprefs.cpu_model == 68060) {
                SET_CFLG (0);
        } else {
                // 68000/010
@@ -799,59 +801,75 @@ void divbyzero_special (bool issigned, uae_s32 dst)
 
 /* DIVU overflow
  *
- * 68000: V=1 N=1
- * 68020: V=1 N=X
- * 68040: V=1
- * 68060: V=1
+ * 68000: V=1, C=0, Z=0, N=1
+ * 68020: V=1, C=0, Z=0, N=X
+ * 68040: V=1, C=0, NZ not modified.
+ * 68060: V=1, C=0, N=0, Z=0
  *
  * X) N is set if original 32-bit destination value is negative.
  *
  */
 
-void setdivuoverflowflags(uae_u32 dividend, uae_u16 divisor)
+void setdivuflags(bool overflow, uae_u32 dividend, uae_u16 divisor)
 {
-       if (currprefs.cpu_model >= 68040) {
-               SET_VFLG(1);
-       } else if (currprefs.cpu_model >= 68020) {
-               SET_VFLG(1);
-               if ((uae_s32)dividend < 0)
-                       SET_NFLG(1);
+       if (!overflow) {
+               if (currprefs.cpu_model != 68040)
+                       CLEAR_CZNV();
        } else {
-               SET_VFLG(1);
-               SET_NFLG(1);
+               if (currprefs.cpu_model == 68060) {
+                       SET_VFLG(1);
+               } else if (currprefs.cpu_model == 68040) {
+                       SET_VFLG(1);
+                       SET_CFLG(0);
+               } else if (currprefs.cpu_model >= 68020) {
+                       SET_VFLG(1);
+                       if ((uae_s32)dividend < 0)
+                               SET_NFLG(1);
+               } else {
+                       SET_VFLG(1);
+                       SET_NFLG(1);
+               }
        }
 }
 
 /*
  * DIVS overflow
  *
- * 68000: V = 1 N = 1
- * 68020: V = 1 ZN = X
- * 68040: V = 1
- * 68060: V = 1
+ * 68000: V=1, C=0, N=1, Z=0
+ * 68020: V=1, C=0, ZN = X
+ * 68040: V=1, C=0. NZ not modified.
+ * 68060: V=1, C=0, N=0, Z=0
  *
  * X) if absolute overflow(Check getDivs68kCycles for details) : Z = 0, N = 0
  * if not absolute overflow : N is set if internal result BYTE is negative, Z is set if it is zero!
  *
  */
 
-void setdivsoverflowflags(uae_s32 dividend, uae_s16 divisor)
+void setdivsflags(bool overflow, uae_s32 dividend, uae_s16 divisor)
 {
-       if (currprefs.cpu_model >= 68040) {
-               SET_VFLG(1);
-       } else if (currprefs.cpu_model >= 68020) {
-               SET_VFLG(1);
-               // absolute overflow?
-               if (((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
-                       return;
-               uae_u32 aquot = (uae_u32)abs(dividend) / (uae_u16)abs(divisor);
-               if ((uae_s8)aquot == 0)
-                       SET_ZFLG(1);
-               if ((uae_s8)aquot < 0)
-                       SET_NFLG(1);
+       if (!overflow) {
+               if (currprefs.cpu_model != 68040)
+                       CLEAR_CZNV();
        } else {
-               SET_VFLG(1);
-               SET_NFLG(1);
+               if (currprefs.cpu_model == 68060) {
+                       SET_VFLG(1);
+               } else if (currprefs.cpu_model == 68040) {
+                       SET_VFLG(1);
+                       SET_CFLG(0);
+               } else if (currprefs.cpu_model >= 68020) {
+                       SET_VFLG(1);
+                       // absolute overflow?
+                       if (((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
+                               return;
+                       uae_u32 aquot = (uae_u32)abs(dividend) / (uae_u16)abs(divisor);
+                       if ((uae_s8)aquot == 0)
+                               SET_ZFLG(1);
+                       if ((uae_s8)aquot < 0)
+                               SET_NFLG(1);
+               } else {
+                       SET_VFLG(1);
+                       SET_NFLG(1);
+               }
        }
 }
 
@@ -957,10 +975,15 @@ STATIC_INLINE int div_unsigned (uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae
 
 static void divl_overflow(void)
 {
-       SET_VFLG(1);
-       SET_NFLG(1);
-       SET_CFLG(0);
-       SET_ZFLG(0);
+       if (currprefs.cpu_model == 68040) {
+               SET_VFLG(1);
+               SET_CFLG(0);
+       } else {
+               SET_VFLG(1);
+               SET_NFLG(1);
+               SET_CFLG(0);
+               SET_ZFLG(0);
+       }
 }
 
 bool m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
@@ -1121,8 +1144,15 @@ bool m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
                SET_CFLG (0);
                if (extra & 0x400) {
                        // 32 * 32 = 64
-                       m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
-                       m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
+                       // 68040 is different.
+                       if (currprefs.cpu_model == 68040) {
+                               m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
+                               m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
+                       } else {
+                               // 020/030/060
+                               m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
+                               m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
+                       }
                        SET_ZFLG(a == 0);
                        SET_NFLG(a < 0);
                } else {
@@ -1144,8 +1174,15 @@ bool m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
                SET_CFLG (0);
                if (extra & 0x400) {
                        // 32 * 32 = 64
-                       m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
-                       m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
+                       // 68040 is different.
+                       if (currprefs.cpu_model == 68040) {
+                               m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
+                               m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
+                       } else {
+                               // 020/030/060
+                               m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
+                               m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
+                       }
                        SET_ZFLG(a == 0);
                        SET_NFLG(((uae_s64)a) < 0);
                } else {