[hatari-devel] BCD fixes

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


Hi guys,

this is my first patch to Hatari and straight into its emulation core. :-) Basically it's PR#127 and PR#129 + the small change for the Hatari tree so you wont have to think about it when merging the change from upstream (as it will be applied already).

As mentioned in the PRs, I have an exhaustive test suite for every possible combination and verified the results against real 000, 030, and 060.

This way I can finally trust Hatari with my experiments not rely on my software emulation in a C function.

P.S. This is also my first Mercurial patch, apologies if I didn't do it 100% right.

--
MiKRO / Mystic Bytes
http://mikro.atari.org
# HG changeset patch
# User Miro Kropacek <miro.kropacek@xxxxxxxxx>
# Date 1515496480 -39600
#      Tue Jan 09 22:14:40 2018 +1100
# Branch mikro
# Node ID d830f7967508cb40fd8f20011e9ab211b999f0e2
# Parent  ddb71e134788707745ebbeb8735e38ba57fd4c09
Fix NBCD

diff -r ddb71e134788 -r d830f7967508 src/cpu/gencpu.c
--- a/src/cpu/gencpu.c	Tue Jan 09 20:41:56 2018 +1100
+++ b/src/cpu/gencpu.c	Tue Jan 09 22:14:40 2018 +1100
@@ -3469,8 +3469,9 @@
 		printf ("\tuae_u16 newv;\n");
 #ifndef WINUAE_FOR_HATARI
 		printf ("\tint cflg, tmp_newv;\n");
+		printf ("\ttmp_newv = newv_hi + newv_lo;\n");
 		printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
-		printf ("\ttmp_newv = newv = newv_hi + newv_lo;\n");
+		printf ("\tnewv = newv_hi + newv_lo;\n");
 #else
 		/* Hatari : use 2 cases to avoid 'tmp_newv' set but not used */
 		if (cpu_level >= xBCD_KEEPS_V_FLAG) {
@@ -3480,8 +3481,9 @@
 		}
 		else {
 			printf ("\tint cflg, tmp_newv;\n");
+			printf ("\ttmp_newv = newv_hi + newv_lo;\n");
 			printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
-			printf ("\ttmp_newv = newv = newv_hi + newv_lo;\n");
+			printf ("\tnewv = newv_hi + newv_lo;\n");
 		}
 #endif
 		printf ("\tcflg = (newv & 0x1F0) > 0x90;\n");
# HG changeset patch
# User Miro Kropacek <miro.kropacek@xxxxxxxxx>
# Date 1515490916 -39600
#      Tue Jan 09 20:41:56 2018 +1100
# Branch mikro
# Node ID ddb71e134788707745ebbeb8735e38ba57fd4c09
# Parent  73223c0d306a7cc408ae4e1c7f8a3c4423567528
Ignore the V flag for BCD calculations on the 030

diff -r 73223c0d306a -r ddb71e134788 src/cpu/gencpu.c
--- a/src/cpu/gencpu.c	Sat Jan 06 09:35:17 2018 +0100
+++ b/src/cpu/gencpu.c	Tue Jan 09 20:41:56 2018 +1100
@@ -31,7 +31,8 @@
 
 #define BOOL_TYPE "int"
 /* Define the minimal 680x0 where NV flags are not affected by xBCD instructions.  */
-#define xBCD_KEEPS_NV_FLAGS 4
+#define xBCD_KEEPS_N_FLAG 4
+#define xBCD_KEEPS_V_FLAG 3
 
 static FILE *headerfile;
 static FILE *stblfile;
@@ -994,7 +995,7 @@
 
 	if (c < 8) // HACK
 		c = 0;
-	
+
 	// c = internal cycles needed after head cycles and before tail cycles. Not total cycles.
 	addcycles_ce020_5 ("op", h, t, c - h - t, -subhead);
 	//printf ("\tregs.irc = get_word_ce020_prefetch (%d);\n", m68k_pc_offset);
@@ -1476,7 +1477,7 @@
 		printf ("\tuaecptr %sa;\n", name);
 		add_mmu040_movem (movem);
 		printf ("\t%sa = m68k_areg (regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword (flags));
-		count_read_ea++; 
+		count_read_ea++;
 		break;
 	case PC16: // (d16,PC)
 		printf ("\tuaecptr %sa;\n", name);
@@ -1522,7 +1523,7 @@
 			} else {
 				printf ("\t%sa = %s (m68k_areg (regs, %s), %s);\n", name, disp000, reg, gen_nextiword (flags));
 			}
-			count_read_ea++; 
+			count_read_ea++;
 		}
 		break;
 	case PC8r: // (d8,PC,Xn)
@@ -2742,7 +2743,7 @@
 	}
 }
 
-// BCHG/BSET/BCLR Dx,Dx or #xx,Dx adds 2 cycles if bit number > 15 
+// BCHG/BSET/BCLR Dx,Dx or #xx,Dx adds 2 cycles if bit number > 15
 static void bsetcycles (struct instr *curi)
 {
 	if (curi->size == sz_byte) {
@@ -2790,7 +2791,7 @@
 	head_ce020_cycs_done = false;
 	no_prefetch_ce020 = false;
 	got_ea_ce020 = false;
-	
+
 	prefetch_long = NULL;
 	prefetch_opcode = NULL;
 	srcli = NULL;
@@ -3321,13 +3322,18 @@
 		printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG () ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n");
 		printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG () ? 1 : 0)) & 0x300) > 0xFF);\n");
 		duplicate_carry (0);
-		/* Manual says bits NV are undefined though a real 68040/060 don't change them */
-		if (cpu_level >= xBCD_KEEPS_NV_FLAGS) {
-			if (next_cpu_level < xBCD_KEEPS_NV_FLAGS)
-				next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1;
+		/* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */
+		if (cpu_level >= xBCD_KEEPS_N_FLAG) {
+			if (next_cpu_level < xBCD_KEEPS_N_FLAG)
+				next_cpu_level = xBCD_KEEPS_N_FLAG - 1;
 			genflags (flag_z, curi->size, "newv", "", "");
 		} else {
 			genflags (flag_zn, curi->size, "newv", "", "");
+		}
+		if (cpu_level >= xBCD_KEEPS_V_FLAG) {
+			if (next_cpu_level < xBCD_KEEPS_V_FLAG)
+				next_cpu_level = xBCD_KEEPS_V_FLAG - 1;
+		} else {
 			printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
 		}
 		if (isreg (curi->smode)) {
@@ -3413,14 +3419,18 @@
 		printf ("\tif (cflg) newv += 0x60;\n");
 		printf ("\tSET_CFLG (cflg);\n");
 		duplicate_carry (0);
-		/* Manual says bits NV are undefined though a real 68040 don't change them */
-		if (cpu_level >= xBCD_KEEPS_NV_FLAGS) {
-			if (next_cpu_level < xBCD_KEEPS_NV_FLAGS)
-				next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1;
+		/* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */
+		if (cpu_level >= xBCD_KEEPS_N_FLAG) {
+			if (next_cpu_level < xBCD_KEEPS_N_FLAG)
+				next_cpu_level = xBCD_KEEPS_N_FLAG - 1;
 			genflags (flag_z, curi->size, "newv", "", "");
+		} else {
+			genflags (flag_zn, curi->size, "newv", "", "");
 		}
-		else {
-			genflags (flag_zn, curi->size, "newv", "", "");
+		if (cpu_level >= xBCD_KEEPS_V_FLAG) {
+			if (next_cpu_level < xBCD_KEEPS_V_FLAG)
+				next_cpu_level = xBCD_KEEPS_V_FLAG - 1;
+		} else {
 			printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n");
 		}
 		if (isreg (curi->smode)) {
@@ -3463,7 +3473,7 @@
 		printf ("\ttmp_newv = newv = newv_hi + newv_lo;\n");
 #else
 		/* Hatari : use 2 cases to avoid 'tmp_newv' set but not used */
-		if (cpu_level >= xBCD_KEEPS_NV_FLAGS) {
+		if (cpu_level >= xBCD_KEEPS_V_FLAG) {
 			printf ("\tint cflg;\n");
 			printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
 			printf ("\tnewv = newv_hi + newv_lo;\n");
@@ -3478,14 +3488,18 @@
 		printf ("\tif (cflg) newv -= 0x60;\n");
 		printf ("\tSET_CFLG (cflg);\n");
 		duplicate_carry(0);
-		/* Manual says bits NV are undefined though a real 68040 don't change them */
-		if (cpu_level >= xBCD_KEEPS_NV_FLAGS) {
-			if (next_cpu_level < xBCD_KEEPS_NV_FLAGS)
-				next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1;
+		/* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */
+		if (cpu_level >= xBCD_KEEPS_N_FLAG) {
+			if (next_cpu_level < xBCD_KEEPS_N_FLAG)
+				next_cpu_level = xBCD_KEEPS_N_FLAG - 1;
 			genflags (flag_z, curi->size, "newv", "", "");
+		} else {
+			genflags (flag_zn, curi->size, "newv", "", "");
 		}
-		else {
-			genflags (flag_zn, curi->size, "newv", "", "");
+		if (cpu_level >= xBCD_KEEPS_V_FLAG) {
+			if (next_cpu_level < xBCD_KEEPS_V_FLAG)
+				next_cpu_level = xBCD_KEEPS_V_FLAG - 1;
+		} else {
 			printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
 		}
 		genastore ("newv", curi->smode, "srcreg", curi->size, "src");
@@ -6144,7 +6158,7 @@
 				opcode_next_clev[rp] = cpu_level;
 		}
 	 }
- 
+
 	if (!using_indirect)
 		using_indirect = using_ce || using_ce020 || using_prefetch_020 || id >= 50;
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/