comparison cpu_dsl.py @ 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 fb5ae8c20b85
children ac809d044cab
comparison
equal deleted inserted replaced
1720:1648c685083a 1721:0e5df2bc0f9f
155 self.implementation = [] 155 self.implementation = []
156 self.args = [] 156 self.args = []
157 self.arg_map = {} 157 self.arg_map = {}
158 self.locals = {} 158 self.locals = {}
159 self.regValues = {} 159 self.regValues = {}
160 self.argValues = {}
160 161
161 def addOp(self, op): 162 def addOp(self, op):
162 if op.op == 'arg': 163 if op.op == 'arg':
163 name = op.params[0] 164 name = op.params[0]
164 size = op.params[1] 165 size = int(op.params[1])
165 self.arg_map[name] = len(self.args) 166 self.arg_map[name] = len(self.args)
166 self.args.append((name, size)) 167 self.args.append((name, size))
167 elif op.op == 'local': 168 elif op.op == 'local':
168 name = op.params[0] 169 name = op.params[0]
169 size = op.params[1] 170 size = op.params[1]
178 179
179 def addLocal(self, name, size): 180 def addLocal(self, name, size):
180 self.locals[name] = size 181 self.locals[name] = size
181 182
182 def localSize(self, name): 183 def localSize(self, name):
183 return self.locals.get(name) 184 if name in self.locals:
185 return self.locals[name]
186 if name in self.arg_map:
187 argIndex = self.arg_map[name]
188 return self.args[argIndex][1]
189 return None
184 190
185 def inline(self, prog, params, output, otype, parent): 191 def inline(self, prog, params, output, otype, parent):
186 if len(params) != len(self.args): 192 if len(params) != len(self.args):
187 raise Exception('{0} expects {1} arguments, but was called with {2}'.format(self.name, len(self.args), len(params))) 193 raise Exception('{0} expects {1} arguments, but was called with {2}'.format(self.name, len(self.args), len(params)))
188 argValues = {} 194 argValues = {}
194 argValues[name] = params[i] 200 argValues[name] = params[i]
195 i += 1 201 i += 1
196 for name in self.locals: 202 for name in self.locals:
197 size = self.locals[name] 203 size = self.locals[name]
198 output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name)) 204 output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name))
205 self.argValues = argValues
199 self.processOps(prog, argValues, output, otype, self.implementation) 206 self.processOps(prog, argValues, output, otype, self.implementation)
200 prog.popScope() 207 prog.popScope()
201 208
202 def __str__(self): 209 def __str__(self):
203 pieces = [self.name] 210 pieces = [self.name]
353 if resultBit > maxBit: 360 if resultBit > maxBit:
354 output.append('\n\t{reg} = {res} >> {shift} & {mask}U;'.format(reg=reg, res=myRes, shift = resultBit - maxBit, mask = 1 << maxBit)) 361 output.append('\n\t{reg} = {res} >> {shift} & {mask}U;'.format(reg=reg, res=myRes, shift = resultBit - maxBit, mask = 1 << maxBit))
355 else: 362 else:
356 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit)) 363 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit))
357 elif calc == 'zero': 364 elif calc == 'zero':
365 if prog.carryFlowDst:
366 realSize = prog.paramSize(prog.lastDst)
367 if realSize != prog.paramSize(prog.carryFlowDst):
368 lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1)
358 if type(storage) is tuple: 369 if type(storage) is tuple:
359 reg,storageBit = storage 370 reg,storageBit = storage
360 reg = prog.resolveParam(reg, None, {}) 371 reg = prog.resolveParam(reg, None, {})
361 output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format( 372 output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format(
362 reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit 373 reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit
526 else: 537 else:
527 dst = params[2] 538 dst = params[2]
528 return decl + '\n\t{dst} = {b} - {a} - ({check} ? 1 : 0);'.format(dst = dst, 539 return decl + '\n\t{dst} = {b} - {a} - ({check} ? 1 : 0);'.format(dst = dst,
529 a = params[0], b = params[1], check=_getCarryCheck(prog) 540 a = params[0], b = params[1], check=_getCarryCheck(prog)
530 ) 541 )
542
543 def _rolCImpl(prog, params, rawParams, flagUpdates):
544 needsCarry = False
545 if flagUpdates:
546 for flag in flagUpdates:
547 calc = prog.flags.flagCalc[flag]
548 if calc == 'carry':
549 needsCarry = True
550 decl = ''
551 size = prog.paramSize(rawParams[2])
552 if needsCarry:
553 decl,name = prog.getTemp(size * 2)
554 dst = prog.carryFlowDst = name
555 else:
556 dst = params[2]
557 return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} - {b});'.format(dst = dst,
558 a = params[0], b = params[1], size=size
559 )
560
561 def _rlcCImpl(prog, params, rawParams, flagUpdates):
562 needsCarry = False
563 if flagUpdates:
564 for flag in flagUpdates:
565 calc = prog.flags.flagCalc[flag]
566 if calc == 'carry':
567 needsCarry = True
568 decl = ''
569 carryCheck = _getCarryCheck(prog)
570 size = prog.paramSize(rawParams[2])
571 if needsCarry:
572 decl,name = prog.getTemp(size * 2)
573 dst = prog.carryFlowDst = name
574 else:
575 dst = params[2]
576 return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({b} - 1);'.format(dst = dst,
577 a = params[0], b = params[1], size=size, check=carryCheck
578 )
579
580 def _rorCImpl(prog, params, rawParams, flagUpdates):
581 needsCarry = False
582 if flagUpdates:
583 for flag in flagUpdates:
584 calc = prog.flags.flagCalc[flag]
585 if calc == 'carry':
586 needsCarry = True
587 decl = ''
588 size = prog.paramSize(rawParams[2])
589 if needsCarry:
590 decl,name = prog.getTemp(size)
591 dst = prog.carryFlowDst = name
592 else:
593 dst = params[2]
594 return decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} - {b});'.format(dst = dst,
595 a = params[0], b = params[1], size=size
596 )
597
598 def _rrcCImpl(prog, params, rawParams, flagUpdates):
599 needsCarry = False
600 if flagUpdates:
601 for flag in flagUpdates:
602 calc = prog.flags.flagCalc[flag]
603 if calc == 'carry':
604 needsCarry = True
605 decl = ''
606 carryCheck = _getCarryCheck(prog)
607 size = prog.paramSize(rawParams[2])
608 if needsCarry:
609 decl,name = prog.getTemp(size * 2)
610 dst = prog.carryFlowDst = name
611 else:
612 dst = params[2]
613 return decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({size}-{b});'.format(dst = dst,
614 a = params[0], b = params[1], size=size, check=carryCheck
615 )
531 616
532 _opMap = { 617 _opMap = {
533 'mov': Op(lambda val: val).cUnaryOperator(''), 618 'mov': Op(lambda val: val).cUnaryOperator(''),
534 'not': Op(lambda val: ~val).cUnaryOperator('~'), 619 'not': Op(lambda val: ~val).cUnaryOperator('~'),
535 'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'), 620 'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'),
539 'sub': Op(lambda a, b: b - a).cBinaryOperator('-'), 624 'sub': Op(lambda a, b: b - a).cBinaryOperator('-'),
540 'sbc': Op().addImplementation('c', 2, _sbcCImpl), 625 'sbc': Op().addImplementation('c', 2, _sbcCImpl),
541 'lsl': Op(lambda a, b: a << b).cBinaryOperator('<<'), 626 'lsl': Op(lambda a, b: a << b).cBinaryOperator('<<'),
542 'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'), 627 'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'),
543 'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl), 628 'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl),
629 'rol': Op().addImplementation('c', 2, _rolCImpl),
630 'rlc': Op().addImplementation('c', 2, _rlcCImpl),
631 'ror': Op().addImplementation('c', 2, _rorCImpl),
632 'rrc': Op().addImplementation('c', 2, _rrcCImpl),
544 'and': Op(lambda a, b: a & b).cBinaryOperator('&'), 633 'and': Op(lambda a, b: a & b).cBinaryOperator('&'),
545 'or': Op(lambda a, b: a | b).cBinaryOperator('|'), 634 'or': Op(lambda a, b: a | b).cBinaryOperator('|'),
546 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'), 635 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'),
547 'abs': Op(lambda val: abs(val)).addImplementation( 636 'abs': Op(lambda val: abs(val)).addImplementation(
548 'c', 1, lambda prog, params: '\n\t{dst} = abs({src});'.format(dst=params[1], src=params[0]) 637 'c', 1, lambda prog, params: '\n\t{dst} = abs({src});'.format(dst=params[1], src=params[0])
626 shortParams = (self.params[0], self.params[-1]) 715 shortParams = (self.params[0], self.params[-1])
627 output.append(_opMap['mov'].generate(otype, prog, shortProc, shortParams, None)) 716 output.append(_opMap['mov'].generate(otype, prog, shortProc, shortParams, None))
628 else: 717 else:
629 output.append(opDef.generate(otype, prog, procParams, self.params, flagUpdates)) 718 output.append(opDef.generate(otype, prog, procParams, self.params, flagUpdates))
630 elif self.op in prog.subroutines: 719 elif self.op in prog.subroutines:
720 procParams = []
721 for param in self.params:
722 begin,sep,end = param.partition('.')
723 if sep:
724 if end in fieldVals:
725 param = begin + '.' + str(fieldVals[end])
726 else:
727 if param in fieldVals:
728 param = fieldVals[param]
729 procParams.append(param)
631 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent) 730 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent)
632 else: 731 else:
633 output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');') 732 output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');')
634 prog.lastOp = self 733 prog.lastOp = self
635 734
1208 if isdst: 1307 if isdst:
1209 self.lastDst = param 1308 self.lastDst = param
1210 return maybeLocal 1309 return maybeLocal
1211 if param in fieldVals: 1310 if param in fieldVals:
1212 param = fieldVals[param] 1311 param = fieldVals[param]
1312 fieldVals = {}
1313 keepGoing = True
1213 elif param in self.meta: 1314 elif param in self.meta:
1214 param = self.meta[param] 1315 param = self.meta[param]
1215 keepGoing = True 1316 keepGoing = True
1216 elif self.isReg(param): 1317 elif self.isReg(param):
1217 return self.resolveReg(param, parent, fieldVals, isdst) 1318 return self.resolveReg(param, parent, fieldVals, isdst)