From: Toni Wilen Date: Sat, 24 Aug 2019 19:02:43 +0000 (+0300) Subject: 68040 specific CPU tester fixes. X-Git-Tag: 4300~138 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=caab579382c418ab1659fc5038021c9b79359bb4;p=francis%2Fwinuae.git 68040 specific CPU tester fixes. --- diff --git a/cputest.cpp b/cputest.cpp index 921b851c..03afa194 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -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) diff --git a/gencpu.cpp b/gencpu.cpp index 8d7ed33d..6b8410bd 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -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 (); diff --git a/include/newcpu.h b/include/newcpu.h index 71757ef7..83d823c5 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -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); diff --git a/newcpu_common.cpp b/newcpu_common.cpp index 3187cd21..618e0a61 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -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 {