changeset 2590:e602dbf776d8

Fix abcd and implement sbcd and nbcd in new 68K core
author Michael Pavone <pavone@retrodev.com>
date Sun, 09 Feb 2025 02:57:37 -0800
parents 6bca3c28e2ad
children 563d05355a12
files m68k.cpu m68k_util.c testcases.txt
diffstat 3 files changed, 199 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/m68k.cpu	Sun Feb 09 02:56:50 2025 -0800
+++ b/m68k.cpu	Sun Feb 09 02:57:37 2025 -0800
@@ -673,42 +673,44 @@
 	update_flags NZV0C0
 	m68k_prefetch
 
-1100XXX100000YYY abcd_dx_dy
-	local lowx 16
-	local lowy 16
-	local highx 16
-	local highy 16
-	lowx = dregs.X & 0xF
-	lowy = dregs.Y & 0xF
-	adc lowx lowy lowy
-	if lowy >=U 0xA
-		lowy += 6
+1100XXX100000YYY abcd_dy_dx
+	local lowx_corf 8
+	local lowy_cmp 8
+	local res 8
+	lowx_corf = dregs.X & 0xF
+	lowy_cmp = dregs.Y & 0xF
+	adc lowx_corf lowy_cmp lowy_cmp
+	if lowy_cmp >=U 0xA
+		lowx_corf = 6
+		lowy_cmp = 0x9A
+	else
+		lowx_corf = 0
+		lowy_cmp = 0xA0
 	end
-	highx = dregs.X & 0xF0
-	highy = dregs.Y & 0xF0
-	highy += highx
-	highy += lowy
-	if highy >=U 0xA0
-		dregs.X:0 = highy + 0x60
-		update_flags X1C1VN
-		highy &= 0xFF
-		if highy
-			update_flags Z0
+	adc dregs.Y dregs.X res 0
+	update_flags XC
+	if cflag
+		lowx_corf |= 0x60
+		res += lowx_corf
+		update_flags NV
+	else
+		if res >=U lowy_cmp
+			lowx_corf |= 0x60
 		end
-	else
-		dregs.X:0 = highy
-		nflag = highy & 128
-		if highy
-			update_flags Z0
-		end
-		update_flags X0C0V0
+		res += lowx_corf
+		update_flags XCNV
 	end
+	if res
+		update_flags Z0
+	end
+	dregs.X:0 = res
 	cycles 2
 	m68k_prefetch
 
-1100XXX100001YYY abcd_ax_ay
-	local lowx 32
-	local lowy 32
+1100XXX100001YYY abcd_ay_ax
+	local lowx_corf 8
+	local lowy_cmp 8
+	local res 8
 	if Y = 7
 		aregs.Y -= 2
 	else
@@ -726,27 +728,34 @@
 	end
 	scratch1 = aregs.X
 	ocall read_8
-	lowx = scratch1 & 0xF
-	lowy = scratch2 & 0xF
-	scratch1 &= 0xF0
-	scratch2 &= 0xF0
-	adc lowx lowy lowy
-	if lowy >=U 0xA
-		lowy += 6
+	lowx_corf = scratch1 & 0xF
+	lowy_cmp = scratch2 & 0xF
+	adc lowx_corf lowy_cmp lowy_cmp
+	if lowy_cmp >=U 0xA
+		lowx_corf = 6
+		lowy_cmp = 0x9A
+	else
+		lowx_corf = 0
+		lowy_cmp = 0xA0
 	end
-	scratch1 += scratch2
-	scratch1 += lowy
-	if scratch1 >=U 0xA0
-		scratch1:0 += 0x60
-		update_flags X1C1VN
+	adc scratch2 scratch1 res 0
+	update_flags XC
+	update_flags XC
+	if cflag
+		lowx_corf |= 0x60
+		res += lowx_corf
+		update_flags NV
 	else
-		cmp 0 scratch1 0
-		update_flags X0C0V0N
+		if res >=U lowy_cmp
+			lowx_corf |= 0x60
+		end
+		res += lowx_corf
+		update_flags XCNV
 	end
-	scratch1 &= 0xFF
-	if scratch1
+	if res
 		update_flags Z0
 	end
+	scratch1 = res
 	scratch2 = aregs.X
 	ocall write_8
 	m68k_prefetch
@@ -1082,6 +1091,81 @@
 	cycles 12 #TODO: where do these occur relative to fetches
 	m68k_prefetch
 
+1000YYY100000XXX sbcd_dx_dy
+	local lowx_corf 8
+	local lowy 8
+	local res 8
+	lowx_corf = dregs.X & 0xF
+	lowy = dregs.Y & 0xF
+	sbc lowx_corf lowy lowy
+	if lowy >=U 0x10
+		lowx_corf = 6
+	else
+		lowx_corf = 0
+	end
+	sbc dregs.X dregs.Y res 0
+	update_flags XC
+	if cflag
+		lowx_corf |= 0x60
+		res -= lowx_corf
+		update_flags NV
+	else
+		res -= lowx_corf
+		update_flags XCNV
+	end
+	if res
+		update_flags Z0
+	end
+	dregs.Y:0 = res
+	cycles 2
+	m68k_prefetch
+
+1000YYY100001XXX sbcd_ax_ay
+	local lowx_corf 8
+	local lowy 8
+	if X = 7
+		aregs.X -= 2
+	else
+		aregs.X -= 1
+	end
+	#predec penalty on src only
+	cycles 2
+	scratch1 = aregs.X
+	ocall read_8
+	scratch2 = scratch1
+	if Y = 7
+		aregs.Y -= 2
+	else
+		aregs.Y -= 1
+	end
+	scratch1 = aregs.Y
+	ocall read_8
+	lowy = scratch1 & 0xF
+	lowx_corf = scratch2 & 0xF
+	sbc lowx_corf lowy lowy
+	if lowy >=U 0x10
+		lowx_corf = 6
+	else
+		lowx_corf = 0
+	end
+	sbc scratch2 scratch1 scratch1 0
+	update_flags XC
+	if cflag
+		lowx_corf |= 0x60
+		scratch1:0 -= lowx_corf
+		update_flags NV
+	else
+		scratch1:0 -= lowx_corf
+		update_flags XCNV
+	end
+	scratch1 &= 0xFF
+	if scratch1
+		update_flags Z0
+	end
+	scratch2 = aregs.Y
+	ocall write_8
+	m68k_prefetch
+
 1000DDD011MMMRRR divu
 	invalid M 1
 	invalid M 7 R 5
@@ -1728,7 +1812,7 @@
 	invalid M 7 R 6
 	invalid M 7 R 7
 	m68k_fetch_src_ea M R 1
-	mov scratch1 ccr
+	mov src ccr
 	cycles 8
 	m68k_prefetch
 
@@ -1739,8 +1823,8 @@
 	invalid M 7 R 7
 	#TODO: privilege violation exception if in user mode
 	m68k_fetch_src_ea M R 1
-	ccr = scratch1
-	status = scratch1 >> 8
+	ccr = src
+	status = src >> 8
 	check_user_mode_swap_ssp_usp
 	update_sync
 	cycles 8
@@ -1806,6 +1890,52 @@
 	m68k_save_dst Z
 	m68k_prefetch
 
+0100100000MMMRRR nbcd
+	local lowx_corf 8
+	local lowy_cmp 8
+	local res 8
+	invalid M 1
+	invalid M 7 R 2
+	invalid M 7 R 3
+	invalid M 7 R 4
+	invalid M 7 R 5
+	invalid M 7 R 6
+	invalid M 7 R 7
+	m68k_fetch_dst_ea M R 0
+	lowx_corf = dst & 0xF
+	lowy_cmp = 0
+	sbc lowx_corf lowy_cmp lowy_cmp
+	if lowy_cmp >= 0xA
+		lowx_corf = 6
+		lowy_cmp = 0xA6
+	else
+		lowx_corf = 0
+		lowy_cmp = 0xA0
+	end
+	res = 0
+	sbc dst res res
+	update_flags XC
+	if cflag
+		lowx_corf |= 0x60
+		res -= lowx_corf
+		update_flags NV
+	else
+		if res >=U lowy_cmp
+			lowx_corf |= 0x60
+		end
+		res -= lowx_corf
+		update_flags XCNV
+	end
+	if res
+		update_flags Z0
+	end
+	dst:0 = res
+	if M = 0
+		cycles 2
+	end
+	m68k_save_dst 0
+	m68k_prefetch
+
 00001100ZZMMMRRR cmpi
 	local immed 32
 	invalid Z 3
--- a/m68k_util.c	Sun Feb 09 02:56:50 2025 -0800
+++ b/m68k_util.c	Sun Feb 09 02:57:37 2025 -0800
@@ -6,11 +6,30 @@
 	context->scratch1 = read_byte(context->scratch1, context->mem_pointers, &context->opts->gen, context);
 }
 
+#ifdef DEBUG_DISASM
+#include "68kinst.h"
+static uint16_t debug_disasm_fetch(uint32_t address, void *vcontext)
+{
+	m68k_context *context = vcontext;
+	return read_word(address, context->mem_pointers, &context->opts->gen, context);
+}
+#endif
 void m68k_read_16(m68k_context *context)
 {
 	context->cycles += 4 * context->opts->gen.clock_divider;
+#ifdef DEBUG_DISASM
 	uint32_t tmp = context->scratch1;
+#endif
 	context->scratch1 = read_word(context->scratch1, context->mem_pointers, &context->opts->gen, context);
+#ifdef DEBUG_DISASM
+	if (tmp == context->pc) {
+		m68kinst inst;
+		m68k_decode(debug_disasm_fetch, context, &inst, tmp);
+		static char disasm_buf[256];
+		m68k_disasm(&inst, disasm_buf);
+		printf("Fetch %05X: %04X - %s, d2 = %X, d3 = %X, d4 = %X, d6 = %X, xflag = %d\n", tmp, context->scratch1, disasm_buf, context->dregs[2], context->dregs[3], context->dregs[4], context->dregs[6], context->xflag);
+	}
+#endif
 }
 
 void m68k_write_8(m68k_context *context)
--- a/testcases.txt	Sun Feb 09 02:56:50 2025 -0800
+++ b/testcases.txt	Sun Feb 09 02:57:37 2025 -0800
@@ -60,6 +60,7 @@
 ext		wl		d
 neg		bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
 negx	bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
+nbcd	b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
 not		bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
 pea		l		(a);(n,a);(n,a,x);(n).w;(n).l;(n,pc);(n,pc,x)
 rol		w		(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l