changeset 2618:1579b840a1af

Implement stop in new 68K core
author Michael Pavone <pavone@retrodev.com>
date Fri, 21 Feb 2025 01:45:04 -0800
parents ad9e074c8901
children ba2aba23b48e
files cpu_dsl.py m68k.cpu
diffstat 2 files changed, 85 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/cpu_dsl.py	Fri Feb 21 00:50:31 2025 -0800
+++ b/cpu_dsl.py	Fri Feb 21 01:45:04 2025 -0800
@@ -45,6 +45,10 @@
 			o = If(self, cond)
 			self.addOp(o)
 			return o
+		elif parts[0] == 'loop':
+			o = Loop(self, None if len(parts) == 1 else parts[1])
+			self.addOp(o)
+			return o
 		elif parts[0] == 'end':
 			raise Exception('end is only allowed inside a switch or if block')
 		else:
@@ -1284,7 +1288,8 @@
 	'xchg': Op().addImplementation('c', (0,1), _xchgCImpl),
 	'dispatch': Op().addImplementation('c', None, _dispatchCImpl),
 	'update_flags': Op().addImplementation('c', None, _updateFlagsCImpl),
-	'update_sync': Op().addImplementation('c', None, _updateSyncCImpl)
+	'update_sync': Op().addImplementation('c', None, _updateSyncCImpl),
+	'break': Op().addImplementation('c', None, lambda prog, params: '\n\tbreak;')
 }
 
 #represents a simple DSL instruction
@@ -1688,6 +1693,56 @@
 		lines.append('\n\tend')
 		return ''.join(lines)
 
+class Loop(ChildBlock):
+	def __init__(self, parent, count):
+		self.op = 'loop'
+		self.parent = parent
+		self.count = count
+		self.body = []
+		self.locals = {}
+		self.regValues = None
+	
+	def addOp(self, op):
+		if op.op in ('case', 'arg', 'else'):
+			raise Exception(op + ' is not allows inside an loop block')
+		if op.op == 'local':
+			name = op.params[0]
+			size = op.params[1]
+			self.locals[name] = size
+		else:
+			self.body.append(op)
+	
+	def localSize(self, name):
+		return self.locals.get(name)
+	
+	def resolveLocal(self, name):
+		if name in self.locals:
+			return name
+		return self.parent.resolveLocal(name)
+	
+	def processDispatch(self, prog):
+		for op in self.body:
+			op.processDispatch(prog)
+	
+	def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
+		self.regValues = parent.regValues
+		if self.count:
+			count = prog.resolveParam(self.count, self, fieldVals)
+			output.append('\n\tfor (uint32_t loop_counter__ = 0; loop_counter__ < {count}; loop_counter__++) {')
+		else:
+			output.append('\n\tfor (;;) {')
+		self.processOps(prog, fieldVals, output, otype, self.body)
+		output.append('\n\t}')
+	
+	def __str__(self):
+		lines = ['\n\tloop']
+		if self.count:
+			lines[0] += f' {self.count}'
+		for op in self.body:
+			lines.append(str(op))
+		lines.append('\n\tend')
+		return ''.join(lines)
+
 class Registers:
 	def __init__(self):
 		self.regs = {}
--- a/m68k.cpu	Fri Feb 21 00:50:31 2025 -0800
+++ b/m68k.cpu	Fri Feb 21 01:45:04 2025 -0800
@@ -60,6 +60,7 @@
 	wp_hit 8
 	trace_pending 8
 	should_return 8
+	stopped 8
 	system ptrvoid
 	reset_handler ptrvoid
 	int_ack_handler ptrvoid
@@ -167,7 +168,6 @@
 			int_pending = int_priority
 			int_pending_num = int_num
 		else
-		
 			#INT_PENDING_SR_CHANGE
 			if 254 = int_pending
 				int_pending = int_priority
@@ -202,7 +202,12 @@
 			
 			#save pc
 			scratch2 = a7 + 2
-			scratch1 = pc - 2
+			if stopped
+				scratch1 = pc
+				stopped = 0
+			else
+				scratch1 = pc - 2
+			end
 			m68k_write32_lowfirst scratch1
 			
 			scratch1 = int_pending_num << 2
@@ -2687,6 +2692,28 @@
 0100111001110001 nop
 	m68k_prefetch
 
+0100111001110010 stop
+	if stopped
+	else
+		mov pc scratch1
+		ocall read_16
+		pc += 2
+		ccr = scratch1
+		status = scratch1 >> 8
+		check_user_mode_swap_ssp_usp
+		update_sync
+		stopped = 1
+	end
+	loop
+		cycles 4
+		if cycles >=U int_cycle
+			break
+		end
+		if cycles >=U target_cycle
+			break
+		end
+	end
+
 0100111001110011 rte
 	#TODO: privilege violation exception if in user mode
 	#Read saved SR