changeset 2591:563d05355a12

Cut down on code bloat in 68K core a little
author Michael Pavone <pavone@retrodev.com>
date Sun, 09 Feb 2025 14:15:22 -0800
parents e602dbf776d8
children 8ef8b2e99f4f
files cpu_dsl.py m68k.cpu
diffstat 2 files changed, 61 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/cpu_dsl.py	Sun Feb 09 02:57:37 2025 -0800
+++ b/cpu_dsl.py	Sun Feb 09 14:15:22 2025 -0800
@@ -88,6 +88,10 @@
 			else:
 				flagUpdates = None
 			oplist[i].generate(prog, self, fieldVals, output, otype, flagUpdates)
+	
+	def processDispatch(self, prog):
+		for op in self.implementation:
+			op.processDispatch(prog)
 		
 	def resolveLocal(self, name):
 		return None
@@ -111,6 +115,7 @@
 		self.invalidFieldValues = {}
 		self.invalidCombos = []
 		self.newLocals = []
+		self.noSpecialize = set()
 		for field in fields:
 			self.varyingBits += fields[field][1]
 	
@@ -131,6 +136,9 @@
 					value = int(op.params[i+1])
 					vmap[name] = value
 				self.invalidCombos.append(vmap)
+		elif op.op == 'nospecialize':
+			for name in op.params:
+				self.noSpecialize.add(name)
 		else:
 			self.implementation.append(op)
 			
@@ -200,6 +208,8 @@
 	
 	def generateName(self, value):
 		fieldVals,fieldBits = self.getFieldVals(value)
+		for name in self.noSpecialize:
+			del fieldVals[name]
 		names = list(fieldVals.keys())
 		names.sort()
 		funName = self.name
@@ -216,7 +226,21 @@
 			output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var))
 		self.newLocals = []
 		fieldVals,_ = self.getFieldVals(value)
+		for name in self.noSpecialize:
+			del fieldVals[name]
+			self.locals[name] = prog.opsize
+			if len(prog.mainDispatch) != 1:
+				raise Exception('nospecialize requires exactly 1 field used for main table dispatch')
+			shift,bits = self.fields[name]
+			mask = (1 << bits) - 1
+			opfield = list(prog.mainDispatch)[0]
+			if shift:
+				output.append(f'\n\tuint{prog.opsize}_t {name} = context->{opfield} >> {shift} & {mask};')
+			else:
+				output.append(f'\n\tuint{prog.opsize}_t {name} = context->{opfield} & {mask};')
 		self.processOps(prog, fieldVals, output, otype, self.implementation)
+		for name in self.noSpecialize:
+			del self.locals[name]
 		
 		if prog.dispatch == 'call':
 			begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context, uint32_t target_cycle)\n{'
@@ -1309,6 +1333,10 @@
 			output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');')
 		prog.lastOp = self
 	
+	def processDispatch(self, prog):
+		if self.op == 'dispatch' and (len(self.params) == 1 or self.params[1] == 'main'):
+			prog.mainDispatch.add(self.params[0])
+	
 	def __str__(self):
 		return '\n\t' + self.op + ' ' + ' '.join(self.params)
 		
@@ -1409,6 +1437,14 @@
 			prog.conditional = oldCond
 		prog.popScope()
 	
+	def processDispatch(self, prog):
+		for case in self.cases:
+			for op in self.cases[case]:
+				op.processDispatch(prog)
+		if self.default:
+			for op in self.default:
+				op.processDispatch(prog)
+	
 	def __str__(self):
 		keys = self.cases.keys()
 		keys.sort()
@@ -1554,6 +1590,12 @@
 					prog.conditional = oldCond
 						
 	
+	def processDispatch(self, prog):
+		for op in self.body:
+			op.processDispatch(prog)
+		for op in self.elseBody:
+			op.processDispatch(prog)
+	
 	def __str__(self):
 		lines = ['\n\tif']
 		for op in self.body:
@@ -1903,9 +1945,12 @@
 						self.needFlagCoalesce = False
 						self.needFlagDisperse = False
 						self.lastOp = None
-						opmap[val] = inst.generateName(val)
-						bodymap[val] = inst.generateBody(val, self, otype)
+						name = inst.generateName(val)
+						opmap[val] = name
+						if not name in bodymap:
+							bodymap[name] = inst.generateBody(val, self, otype)
 		
+		alreadyAppended = set()
 		if self.dispatch == 'call':
 			lateBody.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
 			for inst in range(0, len(opmap)):
@@ -1914,7 +1959,9 @@
 					lateBody.append('\n\tunimplemented,')
 				else:
 					lateBody.append('\n\t' + op + ',')
-					body.append(bodymap[inst])
+					if not op in alreadyAppended:
+						body.append(bodymap[op])
+						alreadyAppended.add(op)
 			lateBody.append('\n};')
 		elif self.dispatch == 'goto':
 			body.append('\n\tstatic void *impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
@@ -1924,7 +1971,8 @@
 					body.append('\n\t\t&&unimplemented,')
 				else:
 					body.append('\n\t\t&&' + op + ',')
-					lateBody.append(bodymap[inst])
+					if not op in alreadyAppended:
+						lateBody.append(bodymap[op])
 			body.append('\n\t};')
 		else:
 			raise Exception("unimplmeneted dispatch type " + self.dispatch)
@@ -1960,6 +2008,12 @@
 		elif self.dispatch == 'goto':
 			body.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type))
 			body.append('\n{')
+		
+		for table in self.instructions:
+			for inst in self.instructions[table]:
+				inst.processDispatch(self)
+		for sub in self.subroutines:
+			self.subroutines[sub].processDispatch(self)
 			
 		for table in self.extra_tables:
 			self._buildTable(otype, table, body, pieces)
--- a/m68k.cpu	Sun Feb 09 02:57:37 2025 -0800
+++ b/m68k.cpu	Sun Feb 09 14:15:22 2025 -0800
@@ -2777,6 +2777,7 @@
 	m68k_prefetch
 
 0111RRR0IIIIIIII moveq
+	nospecialize I
 	local tmp 32
 	sext 16 I tmp
 	sext 32 tmp dregs.R
@@ -2803,6 +2804,7 @@
 	
 	
 01100001DDDDDDDD bsr
+	nospecialize D
 	#mid-instruction timing isn't quite right
 	#becuase I'm only emulating a 1-word prefetch buffer instead of 2
 	local offset 32
@@ -2926,6 +2928,7 @@
 	m68k_prefetch
 
 0110CCCCDDDDDDDD bcc
+	nospecialize D
 	#mid-instruction timing isn't quite right
 	#becuase I'm only emulating a 1-word prefetch buffer instead of 2
 	local offset 32