From: Toni Wilen Date: Mon, 4 Dec 2017 13:52:21 +0000 (+0200) Subject: Accurate DIV overflow undocumented flags. X-Git-Tag: 3600~51 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=1093f40e2e913c700f7ab4fc6c2dbe16470760e2;p=francis%2Fwinuae.git Accurate DIV overflow undocumented flags. --- diff --git a/gencpu.cpp b/gencpu.cpp index 4d869e21..5b267362 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -4371,13 +4371,7 @@ bccl_not68020: /* 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\tSET_VFLG (1);\n"); -#ifdef UNDEF68020 - if (cpu_level >= 2) - printf ("\t\t\tif (currprefs.cpu_level == 0 || dst < 0) SET_NFLG (®s, 1);\n"); - else /* ??? some 68000 revisions may not set NFLG when overflow happens.. */ -#endif - printf ("\t\t\tSET_NFLG (1);\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"); @@ -4412,19 +4406,12 @@ bccl_not68020: addcycles000_nonces("\t\t", "(getDivs68kCycles((uae_s32)dst, (uae_s16)src)) - 4"); fill_prefetch_next (); printf ("\tif (dst == 0x80000000 && src == -1) {\n"); - printf ("\t\tSET_VFLG (1);\n"); - printf ("\t\tSET_NFLG (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\tSET_VFLG (1);\n"); -#ifdef UNDEF68020 - if (cpu_level > 0) - printf ("\t\t\tif (currprefs.cpu_level == 0) SET_NFLG (®s, 1);\n"); - else -#endif - printf ("\t\t\tSET_NFLG (1);\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", "", ""); diff --git a/include/newcpu.h b/include/newcpu.h index e3790155..700e3d9c 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -633,7 +633,9 @@ extern void m68k_dumpstate (uaecptr, uaecptr *); 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 divbyzero_special(bool issigned, uae_s32 dst); +extern void setdivuoverflowflags(uae_u32 dividend, uae_u16 divisor); +extern void setdivsoverflowflags(uae_s32 dividend, uae_u16 divisor); extern void protect_roms (bool); extern void unprotect_maprom (void); extern bool is_hardreset(void); diff --git a/newcpu_common.cpp b/newcpu_common.cpp index 1f82073e..919c98dd 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -771,6 +771,64 @@ 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 + * + * X) N is set if original 32-bit destination value is negative. + * + */ + +void setdivuoverflowflags(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); + } 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 + * + * 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_u16 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); + } else { + SET_VFLG(1); + SET_NFLG(1); + } +} + #ifndef CPUEMU_68000_ONLY #if !defined (uae_s64)