changeset 1618:5dbc453cd345

Getting SVP core closer to compiling
author Michael Pavone <pavone@retrodev.com>
date Mon, 01 Oct 2018 19:11:17 -0700
parents 5e04f9f8bd85
children 0e8438a4c76f
files cpu_dsl.py svp.cpu
diffstat 2 files changed, 128 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/cpu_dsl.py	Tue Sep 25 09:36:00 2018 -0700
+++ b/cpu_dsl.py	Mon Oct 01 19:11:17 2018 -0700
@@ -40,6 +40,7 @@
 		self.regValues = {}
 		self.varyingBits = 0
 		self.invalidFieldValues = {}
+		self.newLocals = []
 		for field in fields:
 			self.varyingBits += fields[field][1]
 	
@@ -62,6 +63,7 @@
 	
 	def addLocal(self, name, size):
 		self.locals[name] = size
+		self.newLocals.append(name)
 		
 	def localSize(self, name):
 		return self.locals.get(name)
@@ -113,10 +115,11 @@
 	def generateBody(self, value, prog, otype):
 		output = []
 		prog.meta = {}
-		prog.currentScope = self
+		prog.pushScope(self)
 		self.regValues = {}
 		for var in self.locals:
 			output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var))
+		self.newLocals = []
 		fieldVals,_ = self.getFieldVals(value)
 		for op in self.implementation:
 			op.generate(prog, self, fieldVals, output, otype)
@@ -125,6 +128,9 @@
 			begin += prog.flags.coalesceFlags(prog, otype)
 		if prog.needFlagDisperse:
 			output.append(prog.flags.disperseFlags(prog, otype))
+		for var in self.newLocals:
+			begin += '\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)
+		prog.popScope()
 		return begin + ''.join(output) + '\n}'
 		
 	def __str__(self):
@@ -175,8 +181,7 @@
 		argValues = {}
 		if parent:
 			self.regValues = parent.regValues
-		oldScope = prog.currentScope
-		prog.currentScope = self
+		prog.pushScope(self)
 		i = 0
 		for name,size in self.args:
 			argValues[name] = params[i]
@@ -186,7 +191,7 @@
 			output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name))
 		for op in self.implementation:
 			op.generate(prog, self, argValues, output, otype)
-		prog.currentScope = oldScope
+		prog.popScope()
 		
 	def __str__(self):
 		pieces = [self.name]
@@ -284,7 +289,7 @@
 	for flag in autoUpdate:
 		calc = prog.flags.flagCalc[flag]
 		calc,_,resultBit = calc.partition('-')
-		lastDst = prog.resolveReg(prog.lastDst, None, {})
+		lastDst = prog.resolveParam(prog.lastDst, None, {})
 		storage = prog.flags.getStorage(flag)
 		if calc == 'bit' or calc == 'sign':
 			if calc == 'sign':
@@ -293,10 +298,10 @@
 				resultBit = int(resultBit)
 			if type(storage) is tuple:
 				reg,storageBit = storage
-				reg = prog.resolveReg(reg, None, {})
+				reg = prog.resolveParam(reg, None, {})
 				if storageBit == resultBit:
 					#TODO: optimize this case
-					output.append('\n\t{reg} = ({reg} & ~{mask}) | ({res} & {mask});'.format(
+					output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format(
 						reg = reg, mask = 1 << resultBit, res = lastDst
 					))
 				else:
@@ -306,26 +311,26 @@
 					else:
 						op = '<<'
 						shift = storageBit - resultBit
-					output.append('\n\t{reg} = ({reg} & ~{mask}) | ({res} {op} {shift} & {mask});'.format(
+					output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} {op} {shift}U & {mask}U);'.format(
 						reg = reg, mask = 1 << storageBit, res = lastDst, op = op, shift = shift
 					))
 			else:
-				reg = prog.resolveReg(storage, None, {})
-				output.append('\n\t{reg} = {res} & {mask};'.format(reg=reg, res=lastDst, mask = 1 << resultBit))
+				reg = prog.resolveParam(storage, None, {})
+				output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=lastDst, mask = 1 << resultBit))
 		elif calc == 'zero':
 			if type(storage) is tuple:
 				reg,storageBit = storage
-				reg = prog.resolveReg(reg, None, {})
-				output.append('\n\t{reg} = {res} ? ({reg} & {mask}) : ({reg} | {bit});'.format(
+				reg = prog.resolveParam(reg, None, {})
+				output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format(
 					reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit
 				))
 			elif prog.paramSize(prog.lastDst) > prog.paramSize(storage):
-				reg = prog.resolveReg(storage, None, {})
+				reg = prog.resolveParam(storage, None, {})
 				output.append('\n\t{reg} = {res} != 0;'.format(
 					reg = reg, res = lastDst
 				))
 			else:
-				reg = prog.resolveReg(storage, None, {})
+				reg = prog.resolveParam(storage, None, {})
 				output.append('\n\t{reg} = {res};'.format(reg = reg, res = lastDst))
 		elif calc == 'half-carry':
 			pass
@@ -357,16 +362,16 @@
 	size = prog.paramSize(params[1])
 	tmpvar = 'cmp_tmp{sz}__'.format(sz=size)
 	typename = ''
-	if not prog.currentScope.resolveLocal(tmpvar):
-		prog.currentScope.addLocal(tmpvar, size)
-		typename = 'uint{sz}_t '.format(sz=size)
+	scope = prog.getRootScope()
+	if not scope.resolveLocal(tmpvar):
+		scope.addLocal(tmpvar, size)
 	prog.lastDst = tmpvar
-	return '\n\t{tp}{var} = {b} - {a};'.format(tp = typename, var = tmpvar, a = params[0], b = params[1])
+	return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1])
 
 def _asrCImpl(prog, params, rawParams):
 	shiftSize = prog.paramSize(rawParams[0])
 	mask = 1 << (shiftSize - 1)
-	return '\n\t{dst} = ({a} >> {b}) | ({a} & {mask}'.format(a = params[0], b = params[1], dst = params[2], mask = mask)
+	return '\n\t{dst} = ({a} >> {b}) | ({a} & {mask});'.format(a = params[0], b = params[1], dst = params[2], mask = mask)
 		
 _opMap = {
 	'mov': Op(lambda val: val).cUnaryOperator(''),
@@ -381,19 +386,22 @@
 	'and': Op(lambda a, b: a & b).cBinaryOperator('&'),
 	'or':  Op(lambda a, b: a | b).cBinaryOperator('|'),
 	'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'),
+	'abs': Op(lambda val: abs(val)).addImplementation(
+		'c', 1, lambda prog, params: '\n\t{dst} = abs({src});'.format(dst=params[1], src=params[0])
+	),
 	'cmp': Op().addImplementation('c', None, _cmpCImpl),
 	'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format(
 		pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]])
 	)),
 	'cycles': Op().addImplementation('c', None,
-		lambda prog, params: '\n\tcontext->current_cycle += context->opts->gen.clock_divider * {0};'.format(
+		lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format(
 			params[0]
 		)
 	),
 	'addsize': Op(
 		lambda a, b: b + (2 * a if a else 1)
 	).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + {sz} ? {sz} * 2 : 1;'.format(
-		dst = params[1], sz = params[0], val = params[1]
+		dst = params[2], sz = params[0], val = params[1]
 	)),
 	'decsize': Op(
 		lambda a, b: b - (2 * a if a else 1)
@@ -509,31 +517,31 @@
 		return self.parent.localSize(name)
 			
 	def generate(self, prog, parent, fieldVals, output, otype):
-		oldScope = prog.currentScope
-		prog.currentScope = self
+		prog.pushScope(self)
 		param = prog.resolveParam(self.param, parent, fieldVals)
 		if type(param) is int:
 			self.regValues = self.parent.regValues
 			if param in self.cases:
-				if self.case_locals[param]:
-					output.append('\n\t{')
-					for local in self.case_locals[param]:
-						output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local))
+				self.current_locals = self.case_locals[param]
+				output.append('\n\t{')
+				for local in self.case_locals[param]:
+					output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local))
 				for op in self.cases[param]:
 					op.generate(prog, self, fieldVals, output, otype)
-				if self.case_locals[param]:
-					output.append('\n\t}')
+				output.append('\n\t}')
 			elif self.default:
-				if self.default_locals:
-					output.append('\n\t{')
-					for local in self.default:
-						output.append('\n\tuint{0}_t {1};'.format(self.default[local], local))
+				self.current_locals = self.default_locals
+				output.append('\n\t{')
+				for local in self.default_locals:
+					output.append('\n\tuint{0}_t {1};'.format(self.default[local], local))
 				for op in self.default:
 					op.generate(prog, self, fieldVals, output, otype)
+				output.append('\n\t}')
 		else:
 			output.append('\n\tswitch(' + param + ')')
 			output.append('\n\t{')
 			for case in self.cases:
+				self.current_locals = self.case_locals[case]
 				self.regValues = dict(self.parent.regValues)
 				output.append('\n\tcase {0}: '.format(case) + '{')
 				for local in self.case_locals[case]:
@@ -543,6 +551,7 @@
 				output.append('\n\tbreak;')
 				output.append('\n\t}')
 			if self.default:
+				self.current_locals = self.default_locals
 				self.regValues = dict(self.parent.regValues)
 				output.append('\n\tdefault: {')
 				for local in self.default_locals:
@@ -550,7 +559,7 @@
 				for op in self.default:
 					op.generate(prog, self, fieldVals, output, otype)
 			output.append('\n\t}')
-		prog.currentScope = oldScope
+		prog.popScope()
 	
 	def __str__(self):
 		keys = self.cases.keys()
@@ -609,55 +618,50 @@
 	def resolveLocal(self, name):
 		if name in self.locals:
 			return name
-		return None
+		return self.parent.resolveLocal(name)
 		
-	def _genTrueBody(self):
+	def _genTrueBody(self, prog, fieldVals, output, otype):
 		self.curLocals = self.locals
+		for local in self.locals:
+			output.append('\n\tuint{sz}_t {nm};'.format(sz=self.locals[local], nm=local))
 		for op in self.body:
 			op.generate(prog, self, fieldVals, output, otype)
 			
-	def _genFalseBody(self):
+	def _genFalseBody(self, prog, fieldVals, output, otype):
 		self.curLocals = self.elseLocals
-		for op in self.body:
+		for local in self.elseLocals:
+			output.append('\n\tuint{sz}_t {nm};'.format(sz=self.elseLocals[local], nm=local))
+		for op in self.elseBody:
 			op.generate(prog, self, fieldVals, output, otype)
 	
-	def _genConstParam(self, param):
+	def _genConstParam(self, param, prog, fieldVals, output, otype):
 		if param:
-			self._genTrueBody()
+			self._genTrueBody(prog, fieldVals, output, otype)
 		else:
-			self._genFalseBody()
+			self._genFalseBody(prog, fieldVals, output, otype)
 			
 	def generate(self, prog, parent, fieldVals, output, otype):
 		self.regValues = parent.regValues
 		try:
-			self._genConstParam(prog.checkBool(self.cond))
+			self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype)
 		except Exception:
 			if self.cond in _ifCmpImpl[otype]:
 				output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output))
-				for op in self.body:
-					op.generate(prog, self, fieldVals, output, otype)
+				self._genTrueBody(prog, fieldVals, output, otype)
 				if self.elseBody:
 					output.append('\n\t} else {')
-					for op in self.elseBody:
-						op.generate(prog, self, fieldVals, output, otype)
+					self._genFalseBody(prog, fieldVals, output, otype)
 				output.append('\n\t}')
 			else:
 				cond = prog.resolveParam(self.cond, parent, fieldVals)
 				if type(cond) is int:
-					if cond:
-						for op in self.body:
-							op.generate(prog, self, fieldVals, output, otype)
-					else:
-						for op in self.elseBody:
-							op.generate(prog, self, fieldVals, output, otype)
+					self._genConstParam(cond, prog, fieldVals, output, otype)
 				else:
 					output.append('\n\tif ({cond}) '.format(cond=cond) + '{')
-					for op in self.body:
-						op.generate(prog, self, fieldVals, output, otype)
+					self._genTrueBody(prog, fieldVals, output, otype)
 					if self.elseBody:
 						output.append('\n\t} else {')
-						for op in self.elseBody:
-							op.generate(prog, self, fieldVals, output, otype)
+						self._genFalseBody(prog, fieldVals, output, otype)
 					output.append('\n\t}')
 						
 	
@@ -718,6 +722,24 @@
 		else:
 			self.addReg(parts[0], int(parts[1]))
 		return self
+
+	def writeHeader(self, otype, hFile):
+		fieldList = []
+		for reg in self.regs:
+			if not self.isRegArrayMember(reg):
+				fieldList.append((self.regs[reg], 1, reg))
+		for arr in self.regArrays:
+			size,regs = self.regArrays[arr]
+			if not type(regs) is int:
+				regs = len(regs)
+			fieldList.append((size, regs, arr))
+		fieldList.sort()
+		fieldList.reverse()
+		for size, count, name in fieldList:
+			if count > 1:
+				hFile.write('\n\tuint{sz}_t {nm}[{ct}];'.format(sz=size, nm=name, ct=count))
+			else:
+				hFile.write('\n\tuint{sz}_t {nm};'.format(sz=size, nm=name))
 	
 class Flags:
 	def __init__(self):
@@ -754,7 +776,7 @@
 		if bit:
 			return (loc, int(bit))
 		else:
-			return loc
+			return loc 
 	
 	def disperseFlags(self, prog, otype):
 		bitToFlag = [None] * (self.maxBit+1)
@@ -872,6 +894,7 @@
 		self.body = info.get('body', [None])[0]
 		self.flags = flags
 		self.lastDst = None
+		self.scopes = []
 		self.currentScope = None
 		self.lastOp = None
 		
@@ -885,6 +908,24 @@
 			pieces.append('\n'+str(instruction))
 		return ''.join(pieces)
 		
+	def writeHeader(self, otype, header):
+		hFile = open(header, 'w')
+		macro = header.upper().replace('.', '_')
+		hFile.write('#ifndef {0}_'.format(macro))
+		hFile.write('\n#define {0}_'.format(macro))
+		hFile.write('\n#include "backend.h"')
+		hFile.write('\n\ntypedef struct {')
+		hFile.write('\n\tcpu_options gen;')
+		hFile.write('\n}} {0}options;'.format(self.prefix))
+		hFile.write('\n\ntypedef struct {')
+		hFile.write('\n\t{0}options *opts;'.format(self.prefix))
+		hFile.write('\n\tuint32_t cycles;')
+		self.regs.writeHeader(otype, hFile)
+		hFile.write('\n}} {0}context;'.format(self.prefix))
+		hFile.write('\n')
+		hFile.write('\n#endif //{0}_'.format(macro))
+		hFile.write('\n')
+		hFile.close()
 	def build(self, otype):
 		body = []
 		pieces = []
@@ -904,7 +945,8 @@
 						opmap[val] = inst.generateName(val)
 						bodymap[val] = inst.generateBody(val, self, otype)
 			
-			pieces.append('\nstatic void *impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
+			pieces.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix))
+			pieces.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
 			for inst in range(0, len(opmap)):
 				op = opmap[inst]
 				if op is None:
@@ -916,13 +958,17 @@
 		if self.body in self.subroutines:
 			pieces.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type))
 			pieces.append('\n{')
-			pieces.append('\n\twhile (context->current_cycle < target_cycle)')
+			pieces.append('\n\twhile (context->cycles < target_cycle)')
 			pieces.append('\n\t{')
 			self.meta = {}
 			self.temp = {}
 			self.subroutines[self.body].inline(self, [], pieces, otype, None)
 			pieces.append('\n\t}')
 			pieces.append('\n}')
+		body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix))
+		body.append('\n{')
+		body.append('\n\tfatal_error("Unimplemented instruction");')
+		body.append('\n}\n')
 		return ''.join(body) +  ''.join(pieces)
 		
 	def checkBool(self, name):
@@ -1020,6 +1066,18 @@
 		if self.regs.isReg(name):
 			return self.regs.regs[name]
 		return 32
+	
+	def pushScope(self, scope):
+		self.scopes.append(scope)
+		self.currentScope = scope
+		
+	def popScope(self):
+		ret = self.scopes.pop()
+		self.currentScope = self.scopes[-1] if self.scopes else None
+		return ret
+		
+	def getRootScope(self):
+		return self.scopes[0]
 
 def parse(f):
 	instructions = {}
@@ -1107,7 +1165,11 @@
 		p.booleans['dynarec'] = False
 		p.booleans['interp'] = True
 		
-		print('#include "m68k_prefix.c"')
+		if 'header' in info:
+			print('#include "{0}"'.format(info['header'][0]))
+			p.writeHeader('c', info['header'][0])
+		print('#include "util.h"')
+		print('#include <stdlib.h>')
 		print(p.build('c'))
 
 def main(argv):
--- a/svp.cpu	Tue Sep 25 09:36:00 2018 -0700
+++ b/svp.cpu	Mon Oct 01 19:11:17 2018 -0700
@@ -2,6 +2,7 @@
 	prefix svp_
 	opcode_size 16
 	body svp_run_op
+	header svp.h
 	
 regs
 	internal 16 scratch1 x y scratch2 st pad pc
@@ -70,9 +71,10 @@
 	case 2
 	#loop decremenet
 	meta modestr -
-	mov reg tmp
 	
 	if rpl
+		local tmp 16
+		mov reg tmp
 		lsl 1 rpl rpl
 		sub 1 rpl rpl
 		local mask 16
@@ -80,7 +82,7 @@
 		and reg mask reg
 		sub 1 tmp tmp
 		and rpl tmp tmp
-		or rpl reg reg
+		or tmp reg reg
 	else
 		sub 1 reg reg
 	end
@@ -91,6 +93,7 @@
 	
 	and 7 st rpl
 	if rpl
+		local tmp 16
 		mov reg tmp
 		lsl 1 rpl rpl
 		sub 1 rpl rpl
@@ -99,7 +102,7 @@
 		and reg mask reg
 		add 1 tmp tmp
 		and rpl tmp tmp
-		or rpl reg reg
+		or tmp reg reg
 	else
 		sub 1 reg reg
 	end