changeset 2562:595719fe69f2

Implement exg, muls and mulu in new 68K core
author Michael Pavone <pavone@retrodev.com>
date Sat, 25 Jan 2025 21:25:01 -0800
parents 8dc8eb079584
children f51d750b4d06
files cpu_dsl.py m68k.cpu
diffstat 2 files changed, 183 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/cpu_dsl.py	Sat Jan 25 19:23:37 2025 -0800
+++ b/cpu_dsl.py	Sat Jan 25 21:25:01 2025 -0800
@@ -15,6 +15,8 @@
 	'-': 'sub',
 	'<<': 'lsl',
 	'>>': 'lsr',
+	'*': 'mulu',
+	'*S': 'muls',
 	'&': 'and',
 	'|': 'or',
 	'^': 'xor'
@@ -751,6 +753,50 @@
 		fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src} & 0x7FFF;'
 	prog.lastSize = params[0]
 	return fmt.format(src=params[1], dst=params[2])
+
+def _mulsCImpl(prog, params, rawParams, flagUpdates):
+	p0Size = prog.paramSize(rawParams[0])
+	p1Size = prog.paramSize(rawParams[1])
+	destSize = prog.paramSize(rawParams[2])
+	if len(params) > 3:
+		size = params[3]
+		if size == 0:
+			size = 8
+		elif size == 1:
+			size = 16
+		else:
+			size = 32
+		prog.lastSize = size
+	else:
+		size = destSize
+	if p0Size >= size:
+		p0Size = size // 2
+	if p1Size >= size:
+		p1Size = size // 2
+	#TODO: Handle case in which destSize > size
+	return f'\n\t{params[2]} = (int{size}_t)(((int{p0Size}_t){params[0]}) * ((int{p1Size}_t){params[1]}));'
+
+def _muluCImpl(prog, params, rawParams, flagUpdates):
+	p0Size = prog.paramSize(rawParams[0])
+	p1Size = prog.paramSize(rawParams[1])
+	destSize = prog.paramSize(rawParams[2])
+	if len(params) > 3:
+		size = params[3]
+		if size == 0:
+			size = 8
+		elif size == 1:
+			size = 16
+		else:
+			size = 32
+		prog.lastSize = size
+	else:
+		size = destSize
+	if p0Size >= size:
+		p0Size = size // 2
+	if p1Size >= size:
+		p1Size = size // 2
+	#TODO: Handle case in which destSize > size
+	return f'\n\t{params[2]} = ((uint{p0Size}_t){params[0]}) * ((uint{p1Size}_t){params[1]});'
 	
 def _getCarryCheck(prog):
 	carryFlag = None
@@ -956,6 +1002,8 @@
 	'rlc': Op().addImplementation('c', 2, _rlcCImpl),
 	'ror': Op().addImplementation('c', 2, _rorCImpl),
 	'rrc': Op().addImplementation('c', 2, _rrcCImpl),
+	'mulu': Op(lambda a, b: a * b).addImplementation('c', 2, _muluCImpl),
+	'muls': Op().addImplementation('c', 2, _mulsCImpl),
 	'and': Op(lambda a, b: a & b).cBinaryOperator('&'),
 	'or':  Op(lambda a, b: a | b).cBinaryOperator('|'),
 	'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'),
@@ -1096,7 +1144,12 @@
 	
 	def addOp(self, op):
 		if op.op == 'case':
-			val = int(op.params[0], 16) if op.params[0].startswith('0x') else int(op.params[0])
+			if op.params[0].startswith('0x'):
+				val = int(op.params[0], 16)
+			elif op.params[0].startswith('0b'):
+				val = int(op.params[0], 2)
+			else:
+				val = int(op.params[0])
 			self.cases[val] = self.current_case = []
 			self.case_locals[val] = self.current_locals = {}
 		elif op.op == 'default':
@@ -1777,6 +1830,8 @@
 					pass
 				elif param.startswith('0x'):
 					param = int(param, 16)
+				elif param.startswith('0b'):
+					param = int(param, 2)
 				else:
 					param = int(param)
 			except ValueError:
--- a/m68k.cpu	Sat Jan 25 19:23:37 2025 -0800
+++ b/m68k.cpu	Sat Jan 25 21:25:01 2025 -0800
@@ -131,6 +131,31 @@
 	ocall read_16
 	lsl tmp 16 tmp
 	or tmp scratch1 scratch1
+
+m68k_trap
+	arg vector 32
+	check_user_mode_swap_ssp_usp
+	#save PC
+	a7 -= 4
+	scratch2 = a7
+	m68k_write32_lowfirst pc
+	#save SR
+	a7 -= 2
+	scratch2 = a7
+	m68k_get_sr
+	ocall write_16
+	#set supervisor bit
+	status |= 0x20
+	#clear trace bit
+	status &= 0x7F
+	trace_pending = 0
+	scratch1 = vector << 2
+	m68k_read32
+	pc = scratch1
+	cycles 10
+	m68k_prefetch
+	
+	
 	
 m68k_interrupt
 	cmp int_cycle cycles
@@ -645,6 +670,102 @@
 	and src dregs.D dregs.D Z
 	update_flags NZV0C0
 	m68k_prefetch
+
+1100XXX101000YYY exg_dn_dn
+	scratch1 = dregs.X
+	dregs.X = dregs.Y
+	dregs.Y = scratch1
+	cycles 2
+	m68k_prefetch
+
+1100XXX101001YYY exg_an_an
+	scratch1 = aregs.X
+	aregs.X = aregs.Y
+	aregs.Y = scratch1
+	cycles 2
+	m68k_prefetch
+
+1100XXX110001YYY exg_dn_an
+	scratch1 = dregs.X
+	dregs.X = aregs.Y
+	aregs.Y = scratch1
+	cycles 2
+	m68k_prefetch
+
+1100DDD011MMMRRR mulu
+	local a 16
+	local b 16
+	invalid M 1
+	invalid M 7 R 5
+	invalid M 7 R 6
+	invalid M 7 R 7
+	
+	m68k_fetch_src_ea M R 1
+	#2-cycles per bit x 16, 2 for cleanup
+	cycles 34
+	#popcnt
+	a = src & 0b1010101010101010
+	a >>= 1
+	b = src & 0b0101010101010101
+	b += a
+	a = b & 0b1100110011001100
+	a >>= 2
+	b &= 0b0011001100110011
+	b += a
+	a = b & 0b1111000011110000
+	a >>= 4
+	b &= 0b0000111100001111
+	b += a
+	a = b & 0b1111111100000000
+	a >>= 8
+	b &= 0b0000000011111111
+	b += a
+	#2 cycles per set bit
+	b += b
+	cycles b
+	dregs.D = src * dregs.D
+	update_flags NZV0C0
+	m68k_prefetch
+
+1100DDD111MMMRRR muls
+	local a 16
+	local b 16
+	invalid M 1
+	invalid M 7 R 5
+	invalid M 7 R 6
+	invalid M 7 R 7
+	
+	m68k_fetch_src_ea M R 1
+	#2-cycles per bit x 16, 2 for cleanup
+	cycles 34
+	#muls timing is essentially the same as muls, but it's based on the number of 0/1
+	#transitions rather than the number of 1 bits. xoring the value with itself shifted
+	#by one effectively sets one bit for every transition
+	b = src << 1
+	b ^= src
+	#popcnt
+	a = b & 0b1010101010101010
+	a >>= 1
+	b &= 0b0101010101010101
+	b += a
+	a = b & 0b1100110011001100
+	a >>= 2
+	b &= 0b0011001100110011
+	b += a
+	a = b & 0b1111000011110000
+	a >>= 4
+	b &= 0b0000111100001111
+	b += a
+	a = b & 0b1111111100000000
+	a >>= 8
+	b &= 0b0000000011111111
+	b += a
+	#2 cycles per set bit
+	b += b
+	cycles b
+	dregs.D = src *S dregs.D
+	update_flags NZV0C0
+	m68k_prefetch
 	
 1100DDD1ZZMMMRRR and_dn_ea
 	invalid M 0
@@ -1876,6 +1997,12 @@
 	update_flags NZV0C0
 	m68k_prefetch
 
+010011100100VVVV trap
+	local vector 32
+	scratch1 = pc
+	vector = V + 32
+	m68k_trap vector
+
 0100111001010RRR link
 	a7 -= 4
 	scratch2 = a7