changeset 1721:0e5df2bc0f9f

Implementation of some of the rotate instructions in new Z80 core
author Michael Pavone <pavone@retrodev.com>
date Thu, 31 Jan 2019 22:41:37 -0800
parents 1648c685083a
children ac809d044cab
files cpu_dsl.py z80.cpu
diffstat 2 files changed, 209 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/cpu_dsl.py	Wed Jan 30 22:11:12 2019 -0800
+++ b/cpu_dsl.py	Thu Jan 31 22:41:37 2019 -0800
@@ -157,11 +157,12 @@
 		self.arg_map = {}
 		self.locals = {}
 		self.regValues = {}
+		self.argValues = {}
 	
 	def addOp(self, op):
 		if op.op == 'arg':
 			name = op.params[0]
-			size = op.params[1]
+			size = int(op.params[1])
 			self.arg_map[name] = len(self.args)
 			self.args.append((name, size))
 		elif op.op == 'local':
@@ -180,7 +181,12 @@
 		self.locals[name] = size
 	
 	def localSize(self, name):
-		return self.locals.get(name)
+		if name in self.locals:
+			return self.locals[name]
+		if name in self.arg_map:
+			argIndex = self.arg_map[name]
+			return self.args[argIndex][1]
+		return None
 			
 	def inline(self, prog, params, output, otype, parent):
 		if len(params) != len(self.args):
@@ -196,6 +202,7 @@
 		for name in self.locals:
 			size = self.locals[name]
 			output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name))
+		self.argValues = argValues
 		self.processOps(prog, argValues, output, otype, self.implementation)
 		prog.popScope()
 		
@@ -355,6 +362,10 @@
 				else:
 					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)
+				if realSize != prog.paramSize(prog.carryFlowDst):
+					lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1)
 			if type(storage) is tuple:
 				reg,storageBit = storage
 				reg = prog.resolveParam(reg, None, {})
@@ -528,6 +539,80 @@
 	return decl + '\n\t{dst} = {b} - {a} - ({check} ? 1 : 0);'.format(dst = dst,
 		a = params[0], b = params[1], check=_getCarryCheck(prog)
 	)
+	
+def _rolCImpl(prog, params, rawParams, flagUpdates):
+	needsCarry = False
+	if flagUpdates:
+		for flag in flagUpdates:
+			calc = prog.flags.flagCalc[flag]
+			if calc == 'carry':
+				needsCarry = True
+	decl = ''
+	size = prog.paramSize(rawParams[2])
+	if needsCarry:
+		decl,name = prog.getTemp(size * 2)
+		dst = prog.carryFlowDst = name
+	else:
+		dst = params[2]
+	return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} - {b});'.format(dst = dst,
+		a = params[0], b = params[1], size=size
+	)
+	
+def _rlcCImpl(prog, params, rawParams, flagUpdates):
+	needsCarry = False
+	if flagUpdates:
+		for flag in flagUpdates:
+			calc = prog.flags.flagCalc[flag]
+			if calc == 'carry':
+				needsCarry = True
+	decl = ''
+	carryCheck = _getCarryCheck(prog)
+	size = prog.paramSize(rawParams[2])
+	if needsCarry:
+		decl,name = prog.getTemp(size * 2)
+		dst = prog.carryFlowDst = name
+	else:
+		dst = params[2]
+	return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({b} - 1);'.format(dst = dst,
+		a = params[0], b = params[1], size=size, check=carryCheck
+	)
+	
+def _rorCImpl(prog, params, rawParams, flagUpdates):
+	needsCarry = False
+	if flagUpdates:
+		for flag in flagUpdates:
+			calc = prog.flags.flagCalc[flag]
+			if calc == 'carry':
+				needsCarry = True
+	decl = ''
+	size = prog.paramSize(rawParams[2])
+	if needsCarry:
+		decl,name = prog.getTemp(size)
+		dst = prog.carryFlowDst = name
+	else:
+		dst = params[2]
+	return decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} - {b});'.format(dst = dst,
+		a = params[0], b = params[1], size=size
+	)
+
+def _rrcCImpl(prog, params, rawParams, flagUpdates):
+	needsCarry = False
+	if flagUpdates:
+		for flag in flagUpdates:
+			calc = prog.flags.flagCalc[flag]
+			if calc == 'carry':
+				needsCarry = True
+	decl = ''
+	carryCheck = _getCarryCheck(prog)
+	size = prog.paramSize(rawParams[2])
+	if needsCarry:
+		decl,name = prog.getTemp(size * 2)
+		dst = prog.carryFlowDst = name
+	else:
+		dst = params[2]
+	return decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({size}-{b});'.format(dst = dst,
+		a = params[0], b = params[1], size=size, check=carryCheck
+	)
 
 _opMap = {
 	'mov': Op(lambda val: val).cUnaryOperator(''),
@@ -541,6 +626,10 @@
 	'lsl': Op(lambda a, b: a << b).cBinaryOperator('<<'),
 	'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'),
 	'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl),
+	'rol': Op().addImplementation('c', 2, _rolCImpl),
+	'rlc': Op().addImplementation('c', 2, _rlcCImpl),
+	'ror': Op().addImplementation('c', 2, _rorCImpl),
+	'rrc': Op().addImplementation('c', 2, _rrcCImpl),
 	'and': Op(lambda a, b: a & b).cBinaryOperator('&'),
 	'or':  Op(lambda a, b: a | b).cBinaryOperator('|'),
 	'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'),
@@ -628,6 +717,16 @@
 			else:
 				output.append(opDef.generate(otype, prog, procParams, self.params, flagUpdates))
 		elif self.op in prog.subroutines:
+			procParams = []
+			for param in self.params:
+				begin,sep,end = param.partition('.')
+				if sep:
+					if end in fieldVals:
+						param = begin + '.' + str(fieldVals[end])
+				else:
+					if param in fieldVals:
+						param = fieldVals[param]
+				procParams.append(param)
 			prog.subroutines[self.op].inline(prog, procParams, output, otype, parent)
 		else:
 			output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');')
@@ -1210,6 +1309,8 @@
 						return maybeLocal
 				if param in fieldVals:
 					param = fieldVals[param]
+					fieldVals = {}
+					keepGoing = True
 				elif param in self.meta:
 					param = self.meta[param]
 					keepGoing = True
--- a/z80.cpu	Wed Jan 30 22:11:12 2019 -0800
+++ b/z80.cpu	Thu Jan 31 22:41:37 2019 -0800
@@ -1,7 +1,7 @@
 info
 	prefix z80_
 	opcode_size 8
-	extra_tables cb ed dded fded dd fd
+	extra_tables cb ed dded fded ddcb fdcb dd fd
 	body z80_run_op
 	include z80_util.c
 	header z80.h
@@ -67,6 +67,22 @@
 	z80_op_fetch
 	dispatch scratch1 fd
 	
+dd 11001011 ddcb_prefix
+	z80_calc_index ix
+	cycles 2
+	mov pc scratch1
+	ocall read_8
+	add 1 pc pc
+	dispatch scratch1 ddcb
+	
+fd 11001011 fdcb_prefix
+	z80_calc_index iy
+	cycles 2
+	mov pc scratch1
+	ocall read_8
+	add 1 pc pc
+	dispatch scratch1 fdcb
+	
 z80_check_cond
 	arg cond 8
 	local invert 8
@@ -867,13 +883,11 @@
 	z80_fetch_index ix
 	and a scratch1 a
 	update_flags SZYH1PXN0C0
-	cycles 3
 	
 fd 10100110 and_iyd
 	z80_fetch_index iy
 	and a scratch1 a
 	update_flags SZYH1PXN0C0
-	cycles 3
 
 11100110 and_immed
 	z80_fetch_immed
@@ -911,13 +925,11 @@
 	z80_fetch_index ix
 	or a scratch1 a
 	update_flags SZYH0PXN0C0
-	cycles 3
 	
 fd 10110110 or_iyd
 	z80_fetch_index iy
 	or a scratch1 a
 	update_flags SZYH0PXN0C0
-	cycles 3
 
 11110110 or_immed
 	z80_fetch_immed
@@ -955,13 +967,11 @@
 	z80_fetch_index ix
 	xor a scratch1 a
 	update_flags SZYH0PXN0C0
-	cycles 3
 	
 fd 10101110 xor_iyd
 	z80_fetch_index iy
 	xor a scratch1 a
 	update_flags SZYH0PXN0C0
-	cycles 3
 
 11101110 xor_immed
 	z80_fetch_immed
@@ -1004,14 +1014,12 @@
 	mov scratch1 last_flag_result
 	cmp scratch1 a
 	update_flags SZHVN1C
-	cycles 3
 	
 fd 10111110 cp_iyd
 	z80_fetch_index iy
 	mov scratch1 last_flag_result
 	cmp scratch1 a
 	update_flags SZHVN1C
-	cycles 3
 
 11111110 cp_immed
 	z80_fetch_immed
@@ -1328,3 +1336,92 @@
 	or c scratch2 scratch2
 	mov main.R scratch1
 	ocall io_write8
+	
+00000111 rlca
+	rol a 1 a
+	update_flags YH0XN0C
+	
+00010111 rla
+	rlc a 1 a
+	update_flags YH0XN0C
+	
+00001111 rrca
+	ror a 1 a
+	update_flags YH0XN0C
+
+00011111 rra
+	rrc a 1 a
+	update_flags YH0XN0C
+	
+cb 00000RRR rlc
+	rol main.R 1 main.R
+	update_flags SZYH0PXN0C
+	
+cb 00000110 rlc_hl
+	local tmp 8
+	z80_fetch_hl
+	mov scratch1 tmp
+	rol tmp 1 tmp
+	update_flags SZYH0PXN0C
+	mov tmp scratch1
+	z80_store_hl
+	
+z80_rlc_index
+	arg tmp 8
+	mov wz scratch1
+	ocall read_8
+	cycles 1
+	mov scratch1 tmp
+	rol tmp 1 tmp
+	update_flags SZYH0PXN0C
+	mov tmp scratch1
+	z80_store_index
+	
+ddcb 00000110 rlc_ixd
+	local tmp 8
+	z80_rlc_index tmp
+	
+ddcb 00000RRR rlc_ixd_reg
+	z80_rlc_index main.R
+	
+fdcb 00000110 rlc_iyd
+	local tmp 8
+	z80_rlc_index tmp
+	
+fdcb 00000RRR rlc_iyd_reg
+	z80_rlc_index main.R
+	
+cb 00010RRR rl
+	rlc main.R 1 main.R
+	update_flags SZYH0PXN0C
+
+cb 00010110 rl_hl
+	local tmp 8
+	z80_fetch_hl
+	mov scratch1 tmp
+	rlc tmp 1 tmp
+	update_flags SZYH0PXN0C
+	mov tmp scratch1
+	z80_store_hl
+	
+ddcb 00010110 rl_ixd
+	local tmp 8
+	mov wz scratch1
+	ocall read_8
+	cycles 1
+	mov scratch1 tmp
+	rlc tmp 1 tmp
+	update_flags SZYH0PXN0C
+	mov tmp scratch1
+	z80_store_index
+	
+fdcb 00010110 rl_iyd
+	local tmp 8
+	mov wz scratch1
+	ocall read_8
+	cycles 1
+	mov scratch1 tmp
+	rlc tmp 1 tmp
+	update_flags SZYH0PXN0C
+	mov tmp scratch1
+	z80_store_index
\ No newline at end of file