diff cpu_dsl.py @ 1838:0c1491818f4b

WIP new 68K core using CPU DSL
author Michael Pavone <pavone@retrodev.com>
date Thu, 18 Apr 2019 19:47:50 -0700
parents 7b6831305a6a
children 9ab5184811ea
line wrap: on
line diff
--- a/cpu_dsl.py	Thu Apr 18 19:47:33 2019 -0700
+++ b/cpu_dsl.py	Thu Apr 18 19:47:50 2019 -0700
@@ -48,6 +48,7 @@
 		self.regValues = {}
 		self.varyingBits = 0
 		self.invalidFieldValues = {}
+		self.invalidCombos = []
 		self.newLocals = []
 		for field in fields:
 			self.varyingBits += fields[field][1]
@@ -58,9 +59,17 @@
 			size = int(op.params[1])
 			self.locals[name] = size
 		elif op.op == 'invalid':
-			name = op.params[0]
-			value = int(op.params[1])
-			self.invalidFieldValues.setdefault(name, set()).add(value)
+			if len(op.params) < 3:
+				name = op.params[0]
+				value = int(op.params[1])
+				self.invalidFieldValues.setdefault(name, set()).add(value)
+			else:
+				vmap = {}
+				for i in range(0, len(op.params), 2):
+					name = op.params[i]
+					value = int(op.params[i+1])
+					vmap[name] = value
+				self.invalidCombos.append(vmap)
 		else:
 			self.implementation.append(op)
 			
@@ -89,12 +98,29 @@
 		for i in range(0, 1 << self.varyingBits):
 			iword = self.value
 			doIt = True
+			combos = []
+			for combo in self.invalidCombos:
+				combos.append(dict(combo))
 			for field in self.fields:
 				shift,bits = self.fields[field]
 				val = i & ((1 << bits) - 1)
 				if field in self.invalidFieldValues and val in self.invalidFieldValues[field]:
 					doIt = False
 					break
+				nextcombos = []
+				for combo in combos:
+					if field in combo:
+						if combo[field] == val:
+							del combo[field]
+							if not combo:
+								doIt = False
+								break
+						else:
+							continue
+					nextcombos.append(combo)
+				combos = nextcombos
+				if not doIt:
+					break
 				i >>= bits
 				iword |= val << shift
 			if doIt:
@@ -132,7 +158,7 @@
 		self.processOps(prog, fieldVals, output, otype, self.implementation)
 		
 		if prog.dispatch == 'call':
-			begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{'
+			begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context, uint32_t target_cycle)\n{'
 		elif prog.dispatch == 'goto':
 			begin = '\n' + self.generateName(value) + ': {'
 		else:
@@ -143,6 +169,8 @@
 			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)
+		for size in prog.temp:
+			begin += '\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size)
 		prog.popScope()
 		if prog.dispatch == 'goto':
 			output += prog.nextInstruction(otype)
@@ -237,6 +265,20 @@
 			else:
 				a = params[0]
 				b = params[1]
+			needsSizeAdjust = False
+			if len(params) > 3:
+				size = params[3]
+				if size == 0:
+					size = 8
+				elif size == 1:
+					size = 16
+				else:
+					size = 32
+				prog.lastSize = size
+				destSize = prog.paramSize(rawParams[2])
+				if destSize > size:
+					needsSizeAdjust = True
+					prog.sizeAdjust = size
 			needsCarry = needsOflow = needsHalf = False
 			if flagUpdates:
 				for flag in flagUpdates:
@@ -248,20 +290,35 @@
 					elif calc == 'overflow':
 						needsOflow = True
 			decl = ''
-			if needsCarry or needsOflow or needsHalf:
-				size = prog.paramSize(rawParams[2])
+			if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust):
+				if len(params) <= 3:
+					size = prog.paramSize(rawParams[2])
 				if needsCarry and op != 'lsr':
 					size *= 2
 				decl,name = prog.getTemp(size)
 				dst = prog.carryFlowDst = name
 				prog.lastA = a
 				prog.lastB = b
+				if size == 64:
+					a = '((uint64_t){a})'.format(a=a)
+					b = '((uint64_t){b})'.format(b=b)
 				prog.lastBFlow = b if op == '-' else '(~{b})'.format(b=b)
+			elif needsSizeAdjust:
+				decl,name = prog.getTemp(size)
+				dst = params[2]
+				return '{decl}\n\t{tmp} = ({a} & {mask}) {op} ({b} & {mask});\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format(
+					decl = decl, tmp = name, a = a, b = b, op = op, dst = dst, mask = ((1 << size) - 1)
+				)
 			else:
 				dst = params[2]
-			return decl + '\n\t{dst} = {a} {op} {b};'.format(
-				dst = dst, a = a, b = b, op = op
-			)
+			if needsSizeAdjust:
+				return decl + '\n\t{dst} = ({a} & {mask}) {op} ({b} & {mask});'.format(
+					dst = dst, a = a, b = b, op = op, mask = (1 << prog.sizeAdjust) - 1
+				)
+			else:
+				return decl + '\n\t{dst} = {a} {op} {b};'.format(
+					dst = dst, a = a, b = b, op = op
+				)
 		self.impls['c'] = _impl
 		self.outOp = (2,)
 		return self
@@ -269,6 +326,20 @@
 		def _impl(prog, params, rawParams, flagUpdates):
 			dst = params[1]
 			decl = ''
+			needsSizeAdjust = False
+			if len(params) > 2:
+				size = params[2]
+				if size == 0:
+					size = 8
+				elif size == 1:
+					size = 16
+				else:
+					size = 32
+				prog.lastSize = size
+				destSize = prog.paramSize(rawParams[1])
+				if destSize > size:
+					needsSizeAdjust = True
+					prog.sizeAdjust = size
 			if op == '-':
 				if flagUpdates:
 					for flag in flagUpdates:
@@ -279,7 +350,7 @@
 							needsHalf = True
 						elif calc == 'overflow':
 							needsOflow = True
-				if needsCarry or needsOflow or needsHalf:
+				if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust):
 					size = prog.paramSize(rawParams[1])
 					if needsCarry:
 						size *= 2
@@ -288,9 +359,14 @@
 					prog.lastA = 0
 					prog.lastB = params[0]
 					prog.lastBFlow = params[0]
-			return decl + '\n\t{dst} = {op}{a};'.format(
-				dst = dst, a = params[0], op = op
-			)
+			if needsSizeAdjust:
+				return decl + '\n\t{dst} = ({dst} & ~{mask}) | (({op}{a}) & {mask});'.format(
+					dst = dst, a = params[0], op = op, mask = (1 << prog.sizeAdjust) - 1
+				)
+			else:
+				return decl + '\n\t{dst} = {op}{a};'.format(
+					dst = dst, a = params[0], op = op
+				)
 		self.impls['c'] = _impl
 		self.outOp = (1,)
 		return self
@@ -336,7 +412,7 @@
 	else:
 		table = params[1]
 	if prog.dispatch == 'call':
-		return '\n\timpl_{tbl}[{op}](context);'.format(tbl = table, op = params[0])
+		return '\n\timpl_{tbl}[{op}](context, target_cycle);'.format(tbl = table, op = params[0])
 	elif prog.dispatch == 'goto':
 		return '\n\tgoto *impl_{tbl}[{op}];'.format(tbl = table, op = params[0])
 	else:
@@ -358,25 +434,25 @@
 		if calc == 'bit' or calc == 'sign' or calc == 'carry' or calc == 'half' or calc == 'overflow':
 			myRes = lastDst
 			if calc == 'sign':
-				resultBit = prog.paramSize(prog.lastDst) - 1
+				resultBit = prog.getLastSize() - 1
 			elif calc == 'carry':
 				if prog.lastOp.op in ('asr', 'lsr'):
 					resultBit = 0
 					myRes = prog.lastA
 				else:
-					resultBit = prog.paramSize(prog.lastDst)
+					resultBit = prog.getLastSize()
 					if prog.lastOp.op == 'ror':
 						resultBit -= 1
 			elif calc == 'half':
-				resultBit = prog.paramSize(prog.lastDst) - 4
+				resultBit = prog.getLastSize() - 4
 				myRes = '({a} ^ {b} ^ {res})'.format(a = prog.lastA, b = prog.lastB, res = lastDst)
 			elif calc == 'overflow':
-				resultBit = prog.paramSize(prog.lastDst) - 1
+				resultBit = prog.getLastSize() - 1
 				myRes = '((({a} ^ {b})) & ({a} ^ {res}))'.format(a = prog.lastA, b = prog.lastBFlow, res = lastDst)
 			else:
 				#Note: offsetting this by the operation size - 8 makes sense for the Z80
 				#but might not for other CPUs with this kind of fixed bit flag behavior
-				resultBit = int(resultBit) + prog.paramSize(prog.lastDst) - 8
+				resultBit = int(resultBit) + prog.getLastSize() - 8
 			if type(storage) is tuple:
 				reg,storageBit = storage
 				if storageBit == resultBit:
@@ -401,7 +477,7 @@
 					output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit))
 		elif calc == 'zero':
 			if prog.carryFlowDst:
-				realSize = prog.paramSize(prog.lastDst)
+				realSize = prog.getLastSize()
 				if realSize != prog.paramSize(prog.carryFlowDst):
 					lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1)
 			if type(storage) is tuple:
@@ -417,7 +493,7 @@
 				))
 		elif calc == 'parity':
 			parity = storage
-			paritySize = prog.paramSize(prog.lastDst)
+			paritySize = prog.getLastSize()
 			if prog.carryFlowDst:
 				parityDst = paritySrc = prog.carryFlowDst
 			else:
@@ -441,7 +517,13 @@
 			))
 	if prog.carryFlowDst:
 		if prog.lastOp.op != 'cmp':
-			output.append('\n\t{dst} = {tmpdst};'.format(dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst))
+			if prog.sizeAdjust:
+				output.append('\n\t{dst} = ({dst} & ~{mask}) | ({tmpdst} & {mask});'.format(
+					dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst, mask = ((1 << prog.sizeAdjust) - 1)
+				))
+				prog.sizeAdjust = None
+			else:
+				output.append('\n\t{dst} = {tmpdst};'.format(dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst))
 		prog.carryFlowDst = None
 	if parity:
 		if paritySize > 8:
@@ -500,6 +582,17 @@
 	if not scope.resolveLocal(tmpvar):
 		scope.addLocal(tmpvar, size)
 	prog.lastDst = rawParams[1]
+	if len(params) > 2:
+		size = params[2]
+		if size == 0:
+			size = 8
+		elif size == 1:
+			size = 16
+		else:
+			size = 32
+		prog.lastSize = size
+	else:
+		prog.lastSize = None
 	return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1])
 
 def _asrCImpl(prog, params, rawParams, flagUpdates):
@@ -523,22 +616,23 @@
 	
 def _sext(size, src):
 	if size == 16:
-		return src | 0xFF00 if src & 0x80 else src
+		return src | 0xFF00 if src & 0x80 else src & 0x7F
 	else:
-		return src | 0xFFFF0000 if src & 0x8000 else src
+		return src | 0xFFFF0000 if src & 0x8000 else src & 0x7FFF
 
 def _sextCImpl(prog, params, rawParms):
 	if params[0] == 16:
-		fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src};'
+		fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src} & 0x7F;'
 	else:
-		fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src};'
+		fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src} & 0x7FFF;'
 	return fmt.format(src=params[1], dst=params[2])
 	
 def _getCarryCheck(prog):
 	carryFlag = None
-	for flag in prog.flags.flagCalc:
+	for flag in prog.flags.flagOrder:
 		if prog.flags.flagCalc[flag] == 'carry':
 			carryFlag = flag
+			break
 	if carryFlag is None:
 		raise Exception('adc requires a defined carry flag')
 	carryStorage = prog.flags.getStorage(carryFlag)
@@ -550,6 +644,20 @@
 		return prog.resolveReg(carryStorage, None, (), False)
 
 def _adcCImpl(prog, params, rawParams, flagUpdates):
+	needsSizeAdjust = False
+	if len(params) > 3:
+		size = params[3]
+		if size == 0:
+			size = 8
+		elif size == 1:
+			size = 16
+		else:
+			size = 32
+		prog.lastSize = size
+		destSize = prog.paramSize(rawParams[2])
+		if destSize > size:
+			needsSizeAdjust = True
+			prog.sizeAdjust = size
 	needsCarry = needsOflow = needsHalf = False
 	if flagUpdates:
 		for flag in flagUpdates:
@@ -562,8 +670,10 @@
 				needsOflow = True
 	decl = ''
 	carryCheck = _getCarryCheck(prog)
-	if needsCarry or needsOflow or needsHalf:
-		size = prog.paramSize(rawParams[2])
+	vals = '1 : 0'
+	if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust):
+		if len(params) <= 3:
+			size = prog.paramSize(rawParams[2])
 		if needsCarry:
 			size *= 2
 		decl,name = prog.getTemp(size)
@@ -571,13 +681,37 @@
 		prog.lastA = params[0]
 		prog.lastB = params[1]
 		prog.lastBFlow = '(~{b})'.format(b=params[1])
+		if size == 64:
+			params[0] = '((uint64_t){a})'.format(a=params[0])
+			params[1] = '((uint64_t){b})'.format(b=params[1])
+			vals = '((uint64_t)1) : ((uint64_t)0)'
+	elif needsSizeAdjust:
+		decl,name = prog.getTemp(size)
+		dst = params[2]
+		return '{decl}\n\t{tmp} = ({a} & {mask}) + ({b} & {mask}) + ({check} ? 1 : 0);\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format(
+			decl = decl, tmp = name, a = a, b = b, op = op, dst = dst, mask = ((1 << size) - 1), check = carryCheck
+		)
 	else:
 		dst = params[2]
-	return decl + '\n\t{dst} = {a} + {b} + ({check} ? 1 : 0);'.format(dst = dst,
-		a = params[0], b = params[1], check = carryCheck
+	return decl + '\n\t{dst} = {a} + {b} + ({check} ? {vals});'.format(dst = dst,
+		a = params[0], b = params[1], check = carryCheck, vals = vals
 	)
 
 def _sbcCImpl(prog, params, rawParams, flagUpdates):
+	needsSizeAdjust = False
+	if len(params) > 3:
+		size = params[3]
+		if size == 0:
+			size = 8
+		elif size == 1:
+			size = 16
+		else:
+			size = 32
+		prog.lastSize = size
+		destSize = prog.paramSize(rawParams[2])
+		if destSize > size:
+			needsSizeAdjust = True
+			prog.sizeAdjust = size
 	needsCarry = needsOflow = needsHalf = False
 	if flagUpdates:
 		for flag in flagUpdates:
@@ -590,7 +724,8 @@
 				needsOflow = True
 	decl = ''
 	carryCheck = _getCarryCheck(prog)
-	if needsCarry or needsOflow or needsHalf:
+	vals = '1 : 0'
+	if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust):
 		size = prog.paramSize(rawParams[2])
 		if needsCarry:
 			size *= 2
@@ -599,10 +734,20 @@
 		prog.lastA = params[1]
 		prog.lastB = params[0]
 		prog.lastBFlow = params[0]
+		if size == 64:
+			params[1] = '((uint64_t){a})'.format(a=params[1])
+			params[0] = '((uint64_t){b})'.format(b=params[0])
+			vals = '((uint64_t)1) : ((uint64_t)0)'
+	elif needsSizeAdjust:
+		decl,name = prog.getTemp(size)
+		dst = params[2]
+		return '{decl}\n\t{tmp} = ({b} & {mask}) - ({a} & {mask}) - ({check} ? 1 : 0);\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format(
+			decl = decl, tmp = name, a = params[0], b = params[1], op = op, dst = dst, mask = ((1 << size) - 1), check = carryCheck
+		)
 	else:
 		dst = params[2]
-	return decl + '\n\t{dst} = {b} - {a} - ({check} ? 1 : 0);'.format(dst = dst,
-		a = params[0], b = params[1], check=_getCarryCheck(prog)
+	return decl + '\n\t{dst} = {b} - {a} - ({check} ? {vals});'.format(dst = dst,
+		a = params[0], b = params[1], check=_getCarryCheck(prog), vals = vals
 	)
 	
 def _rolCImpl(prog, params, rawParams, flagUpdates):
@@ -697,6 +842,9 @@
 	'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:]])
 	)),
+	'pcall': Op().addImplementation('c', None, lambda prog, params: '\n\t(({typ}){fun})({args});'.format(
+		typ = params[1], fun = params[0], args = ', '.join([str(p) for p in params[2:]])
+	)),
 	'cycles': Op().addImplementation('c', None,
 		lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format(
 			params[0]
@@ -704,12 +852,12 @@
 	),
 	'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(
+	).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + ({sz} ? {sz} * 2 : 1);'.format(
 		dst = params[2], sz = params[0], val = params[1]
 	)),
 	'decsize': 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(
+	).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - ({sz} ? {sz} * 2 : 1);'.format(
 		dst = params[2], sz = params[0], val = params[1]
 	)),
 	'xchg': Op().addImplementation('c', (0,1), _xchgCImpl),
@@ -729,8 +877,8 @@
 		allParamsConst = flagUpdates is None and not prog.conditional
 		opDef = _opMap.get(self.op)
 		for param in self.params:
-			allowConst = (self.op in prog.subroutines or len(procParams) != len(self.params) - 1) and param in parent.regValues
 			isDst = (not opDef is None) and len(procParams) in opDef.outOp
+			allowConst = (self.op in prog.subroutines or not isDst) and param in parent.regValues
 			if isDst and self.op == 'xchg':
 				#xchg uses its regs as both source and destination
 				#we need to resolve as both so that disperse/coalesce flag stuff gets done
@@ -794,6 +942,10 @@
 				else:
 					if param in fieldVals:
 						param = fieldVals[param]
+					else:
+						maybeLocal = parent.resolveLocal(param)
+						if maybeLocal and maybeLocal in parent.regValues:
+							param = parent.regValues[maybeLocal]
 				procParams.append(param)
 			prog.subroutines[self.op].inline(prog, procParams, output, otype, parent)
 		else:
@@ -872,7 +1024,7 @@
 			output.append('\n\tswitch(' + param + ')')
 			output.append('\n\t{')
 			for case in self.cases:
-				temp = prog.temp.copy()
+				#temp = prog.temp.copy()
 				self.current_locals = self.case_locals[case]
 				self.regValues = dict(self.parent.regValues)
 				output.append('\n\tcase {0}U: '.format(case) + '{')
@@ -881,16 +1033,16 @@
 				self.processOps(prog, fieldVals, output, otype, self.cases[case])
 				output.append('\n\tbreak;')
 				output.append('\n\t}')
-				prog.temp = temp
+				#prog.temp = temp
 			if self.default:
-				temp = prog.temp.copy()
+				#temp = prog.temp.copy()
 				self.current_locals = self.default_locals
 				self.regValues = dict(self.parent.regValues)
 				output.append('\n\tdefault: {')
 				for local in self.default_locals:
 					output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local))
 				self.processOps(prog, fieldVals, output, otype, self.default)
-				prog.temp = temp
+				#prog.temp = temp
 			output.append('\n\t}')
 			prog.conditional = oldCond
 		prog.popScope()
@@ -915,10 +1067,15 @@
 		raise Exception(">=U not implemented in the general case yet")
 
 def _eqCImpl(prog, parent, fieldVals, output):
-	return '\n\tif (!{a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {}))
+	if prog.lastOp.op == 'cmp':
+		output.pop()
+		params = [prog.resolveParam(p, parent, fieldVals) for p in prog.lastOp.params]
+		return '\n\tif ({a} == {b}) '.format(a=params[1], b = params[0]) + '{'
+	else:
+		return '\n\tif (!{a}) {{'.format(a=prog.resolveParam(prog.lastDst, None, {}))
 
 def _neqCImpl(prog, parent, fieldVals, output):
-	return '\n\tif ({a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {}))
+	return '\n\tif ({a}) {{'.format(a=prog.resolveParam(prog.lastDst, None, {}))
 	
 _ifCmpImpl = {
 	'c': {
@@ -986,21 +1143,21 @@
 			
 	def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
 		self.regValues = parent.regValues
-		try:
+		if self.cond in prog.booleans:
 			self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype)
-		except Exception:
+		else:
 			if self.cond in _ifCmpImpl[otype]:
 				oldCond = prog.conditional
 				prog.conditional = True
-				temp = prog.temp.copy()
+				#temp = prog.temp.copy()
 				output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output))
 				self._genTrueBody(prog, fieldVals, output, otype)
-				prog.temp = temp
+				#prog.temp = temp
 				if self.elseBody:
-					temp = prog.temp.copy()
+					#temp = prog.temp.copy()
 					output.append('\n\t} else {')
 					self._genFalseBody(prog, fieldVals, output, otype)
-					prog.temp = temp
+					#prog.temp = temp
 				output.append('\n\t}')
 				prog.conditional = oldCond
 			else:
@@ -1008,17 +1165,17 @@
 				if type(cond) is int:
 					self._genConstParam(cond, prog, fieldVals, output, otype)
 				else:
-					temp = prog.temp.copy()
+					#temp = prog.temp.copy()
 					output.append('\n\tif ({cond}) '.format(cond=cond) + '{')
 					oldCond = prog.conditional
 					prog.conditional = True
 					self._genTrueBody(prog, fieldVals, output, otype)
-					prog.temp = temp
+					#prog.temp = temp
 					if self.elseBody:
-						temp = prog.temp.copy()
+						#temp = prog.temp.copy()
 						output.append('\n\t} else {')
 						self._genFalseBody(prog, fieldVals, output, otype)
-						prog.temp = temp
+						#prog.temp = temp
 					output.append('\n\t}')
 					prog.conditional = oldCond
 						
@@ -1129,6 +1286,7 @@
 		self.flagBits = {}
 		self.flagCalc = {}
 		self.flagStorage = {}
+		self.flagOrder = []
 		self.flagReg = None
 		self.storageToFlags = {}
 		self.maxBit = -1
@@ -1153,6 +1311,7 @@
 			self.flagStorage[flag] = storage
 			storage,_,storebit = storage.partition('.')
 			self.storageToFlags.setdefault(storage, []).append((storebit, flag))
+			self.flagOrder.append(flag)
 		return self
 	
 	def getStorage(self, flag):
@@ -1312,8 +1471,10 @@
 		self.lastA = None
 		self.lastB = None
 		self.lastBFlow = None
+		self.sizeAdjust = None
 		self.conditional = False
 		self.declares = []
+		self.lastSize = None
 		
 	def __str__(self):
 		pieces = []
@@ -1411,11 +1572,11 @@
 		for include in self.includes:
 			body.append('#include "{0}"\n'.format(include))
 		if self.dispatch == 'call':
-			body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix))
+			body.append('\nstatic void unimplemented({pre}context *context, uint32_t target_cycle)'.format(pre = self.prefix))
 			body.append('\n{')
 			body.append('\n\tfatal_error("Unimplemented instruction\\n");')
 			body.append('\n}\n')
-			body.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix))
+			body.append('\ntypedef void (*impl_fun)({pre}context *context, uint32_t target_cycle);'.format(pre=self.prefix))
 			for table in self.extra_tables:
 				body.append('\nstatic impl_fun impl_{name}[{sz}];'.format(name = table, sz=(1 << self.opsize)))
 			body.append('\nstatic impl_fun impl_main[{sz}];'.format(sz=(1 << self.opsize)))
@@ -1455,7 +1616,7 @@
 		if size in self.temp:
 			return ('', self.temp[size])
 		self.temp[size] = 'gen_tmp{sz}__'.format(sz=size);
-		return ('\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size), self.temp[size])
+		return ('', self.temp[size])
 		
 	def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False):
 		keepGoing = True
@@ -1477,6 +1638,7 @@
 					if maybeLocal:
 						if isdst:
 							self.lastDst = param
+							self.lastSize = None
 						return maybeLocal
 				if param in fieldVals:
 					param = fieldVals[param]
@@ -1487,8 +1649,11 @@
 					keepGoing = True
 				elif self.isReg(param):
 					return self.resolveReg(param, parent, fieldVals, isdst)
+				elif param in self.regs.pointers:
+					return 'context->' + param
 		if isdst:
 			self.lastDst = param
+			self.lastSize = None
 		return param
 	
 	def isReg(self, name):
@@ -1551,6 +1716,11 @@
 			return self.regs.regs[name]
 		return 32
 	
+	def getLastSize(self):
+		if self.lastSize:
+			return self.lastSize
+		return self.paramSize(self.lastDst)
+	
 	def pushScope(self, scope):
 		self.scopes.append(scope)
 		self.currentScope = scope