Mercurial > repos > blastem
comparison cpu_dsl.py @ 1618:5dbc453cd345
Getting SVP core closer to compiling
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 01 Oct 2018 19:11:17 -0700 |
parents | 8c78543c4783 |
children | 0e8438a4c76f |
comparison
equal
deleted
inserted
replaced
1617:5e04f9f8bd85 | 1618:5dbc453cd345 |
---|---|
38 self.implementation = [] | 38 self.implementation = [] |
39 self.locals = {} | 39 self.locals = {} |
40 self.regValues = {} | 40 self.regValues = {} |
41 self.varyingBits = 0 | 41 self.varyingBits = 0 |
42 self.invalidFieldValues = {} | 42 self.invalidFieldValues = {} |
43 self.newLocals = [] | |
43 for field in fields: | 44 for field in fields: |
44 self.varyingBits += fields[field][1] | 45 self.varyingBits += fields[field][1] |
45 | 46 |
46 def addOp(self, op): | 47 def addOp(self, op): |
47 if op.op == 'local': | 48 if op.op == 'local': |
60 return name | 61 return name |
61 return None | 62 return None |
62 | 63 |
63 def addLocal(self, name, size): | 64 def addLocal(self, name, size): |
64 self.locals[name] = size | 65 self.locals[name] = size |
66 self.newLocals.append(name) | |
65 | 67 |
66 def localSize(self, name): | 68 def localSize(self, name): |
67 return self.locals.get(name) | 69 return self.locals.get(name) |
68 | 70 |
69 def __lt__(self, other): | 71 def __lt__(self, other): |
111 return funName | 113 return funName |
112 | 114 |
113 def generateBody(self, value, prog, otype): | 115 def generateBody(self, value, prog, otype): |
114 output = [] | 116 output = [] |
115 prog.meta = {} | 117 prog.meta = {} |
116 prog.currentScope = self | 118 prog.pushScope(self) |
117 self.regValues = {} | 119 self.regValues = {} |
118 for var in self.locals: | 120 for var in self.locals: |
119 output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)) | 121 output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)) |
122 self.newLocals = [] | |
120 fieldVals,_ = self.getFieldVals(value) | 123 fieldVals,_ = self.getFieldVals(value) |
121 for op in self.implementation: | 124 for op in self.implementation: |
122 op.generate(prog, self, fieldVals, output, otype) | 125 op.generate(prog, self, fieldVals, output, otype) |
123 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{' | 126 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{' |
124 if prog.needFlagCoalesce: | 127 if prog.needFlagCoalesce: |
125 begin += prog.flags.coalesceFlags(prog, otype) | 128 begin += prog.flags.coalesceFlags(prog, otype) |
126 if prog.needFlagDisperse: | 129 if prog.needFlagDisperse: |
127 output.append(prog.flags.disperseFlags(prog, otype)) | 130 output.append(prog.flags.disperseFlags(prog, otype)) |
131 for var in self.newLocals: | |
132 begin += '\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var) | |
133 prog.popScope() | |
128 return begin + ''.join(output) + '\n}' | 134 return begin + ''.join(output) + '\n}' |
129 | 135 |
130 def __str__(self): | 136 def __str__(self): |
131 pieces = [self.name + ' ' + hex(self.value) + ' ' + str(self.fields)] | 137 pieces = [self.name + ' ' + hex(self.value) + ' ' + str(self.fields)] |
132 for name in self.locals: | 138 for name in self.locals: |
173 if len(params) != len(self.args): | 179 if len(params) != len(self.args): |
174 raise Exception('{0} expects {1} arguments, but was called with {2}'.format(self.name, len(self.args), len(params))) | 180 raise Exception('{0} expects {1} arguments, but was called with {2}'.format(self.name, len(self.args), len(params))) |
175 argValues = {} | 181 argValues = {} |
176 if parent: | 182 if parent: |
177 self.regValues = parent.regValues | 183 self.regValues = parent.regValues |
178 oldScope = prog.currentScope | 184 prog.pushScope(self) |
179 prog.currentScope = self | |
180 i = 0 | 185 i = 0 |
181 for name,size in self.args: | 186 for name,size in self.args: |
182 argValues[name] = params[i] | 187 argValues[name] = params[i] |
183 i += 1 | 188 i += 1 |
184 for name in self.locals: | 189 for name in self.locals: |
185 size = self.locals[name] | 190 size = self.locals[name] |
186 output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name)) | 191 output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name)) |
187 for op in self.implementation: | 192 for op in self.implementation: |
188 op.generate(prog, self, argValues, output, otype) | 193 op.generate(prog, self, argValues, output, otype) |
189 prog.currentScope = oldScope | 194 prog.popScope() |
190 | 195 |
191 def __str__(self): | 196 def __str__(self): |
192 pieces = [self.name] | 197 pieces = [self.name] |
193 for name,size in self.args: | 198 for name,size in self.args: |
194 pieces.append('\n\targ {0} {1}'.format(name, size)) | 199 pieces.append('\n\targ {0} {1}'.format(name, size)) |
282 output = [] | 287 output = [] |
283 #TODO: handle autoUpdate flags | 288 #TODO: handle autoUpdate flags |
284 for flag in autoUpdate: | 289 for flag in autoUpdate: |
285 calc = prog.flags.flagCalc[flag] | 290 calc = prog.flags.flagCalc[flag] |
286 calc,_,resultBit = calc.partition('-') | 291 calc,_,resultBit = calc.partition('-') |
287 lastDst = prog.resolveReg(prog.lastDst, None, {}) | 292 lastDst = prog.resolveParam(prog.lastDst, None, {}) |
288 storage = prog.flags.getStorage(flag) | 293 storage = prog.flags.getStorage(flag) |
289 if calc == 'bit' or calc == 'sign': | 294 if calc == 'bit' or calc == 'sign': |
290 if calc == 'sign': | 295 if calc == 'sign': |
291 resultBit = prog.paramSize(prog.lastDst) - 1 | 296 resultBit = prog.paramSize(prog.lastDst) - 1 |
292 else: | 297 else: |
293 resultBit = int(resultBit) | 298 resultBit = int(resultBit) |
294 if type(storage) is tuple: | 299 if type(storage) is tuple: |
295 reg,storageBit = storage | 300 reg,storageBit = storage |
296 reg = prog.resolveReg(reg, None, {}) | 301 reg = prog.resolveParam(reg, None, {}) |
297 if storageBit == resultBit: | 302 if storageBit == resultBit: |
298 #TODO: optimize this case | 303 #TODO: optimize this case |
299 output.append('\n\t{reg} = ({reg} & ~{mask}) | ({res} & {mask});'.format( | 304 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format( |
300 reg = reg, mask = 1 << resultBit, res = lastDst | 305 reg = reg, mask = 1 << resultBit, res = lastDst |
301 )) | 306 )) |
302 else: | 307 else: |
303 if resultBit > storageBit: | 308 if resultBit > storageBit: |
304 op = '>>' | 309 op = '>>' |
305 shift = resultBit - storageBit | 310 shift = resultBit - storageBit |
306 else: | 311 else: |
307 op = '<<' | 312 op = '<<' |
308 shift = storageBit - resultBit | 313 shift = storageBit - resultBit |
309 output.append('\n\t{reg} = ({reg} & ~{mask}) | ({res} {op} {shift} & {mask});'.format( | 314 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} {op} {shift}U & {mask}U);'.format( |
310 reg = reg, mask = 1 << storageBit, res = lastDst, op = op, shift = shift | 315 reg = reg, mask = 1 << storageBit, res = lastDst, op = op, shift = shift |
311 )) | 316 )) |
312 else: | 317 else: |
313 reg = prog.resolveReg(storage, None, {}) | 318 reg = prog.resolveParam(storage, None, {}) |
314 output.append('\n\t{reg} = {res} & {mask};'.format(reg=reg, res=lastDst, mask = 1 << resultBit)) | 319 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=lastDst, mask = 1 << resultBit)) |
315 elif calc == 'zero': | 320 elif calc == 'zero': |
316 if type(storage) is tuple: | 321 if type(storage) is tuple: |
317 reg,storageBit = storage | 322 reg,storageBit = storage |
318 reg = prog.resolveReg(reg, None, {}) | 323 reg = prog.resolveParam(reg, None, {}) |
319 output.append('\n\t{reg} = {res} ? ({reg} & {mask}) : ({reg} | {bit});'.format( | 324 output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format( |
320 reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit | 325 reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit |
321 )) | 326 )) |
322 elif prog.paramSize(prog.lastDst) > prog.paramSize(storage): | 327 elif prog.paramSize(prog.lastDst) > prog.paramSize(storage): |
323 reg = prog.resolveReg(storage, None, {}) | 328 reg = prog.resolveParam(storage, None, {}) |
324 output.append('\n\t{reg} = {res} != 0;'.format( | 329 output.append('\n\t{reg} = {res} != 0;'.format( |
325 reg = reg, res = lastDst | 330 reg = reg, res = lastDst |
326 )) | 331 )) |
327 else: | 332 else: |
328 reg = prog.resolveReg(storage, None, {}) | 333 reg = prog.resolveParam(storage, None, {}) |
329 output.append('\n\t{reg} = {res};'.format(reg = reg, res = lastDst)) | 334 output.append('\n\t{reg} = {res};'.format(reg = reg, res = lastDst)) |
330 elif calc == 'half-carry': | 335 elif calc == 'half-carry': |
331 pass | 336 pass |
332 elif calc == 'carry': | 337 elif calc == 'carry': |
333 pass | 338 pass |
355 | 360 |
356 def _cmpCImpl(prog, params): | 361 def _cmpCImpl(prog, params): |
357 size = prog.paramSize(params[1]) | 362 size = prog.paramSize(params[1]) |
358 tmpvar = 'cmp_tmp{sz}__'.format(sz=size) | 363 tmpvar = 'cmp_tmp{sz}__'.format(sz=size) |
359 typename = '' | 364 typename = '' |
360 if not prog.currentScope.resolveLocal(tmpvar): | 365 scope = prog.getRootScope() |
361 prog.currentScope.addLocal(tmpvar, size) | 366 if not scope.resolveLocal(tmpvar): |
362 typename = 'uint{sz}_t '.format(sz=size) | 367 scope.addLocal(tmpvar, size) |
363 prog.lastDst = tmpvar | 368 prog.lastDst = tmpvar |
364 return '\n\t{tp}{var} = {b} - {a};'.format(tp = typename, var = tmpvar, a = params[0], b = params[1]) | 369 return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1]) |
365 | 370 |
366 def _asrCImpl(prog, params, rawParams): | 371 def _asrCImpl(prog, params, rawParams): |
367 shiftSize = prog.paramSize(rawParams[0]) | 372 shiftSize = prog.paramSize(rawParams[0]) |
368 mask = 1 << (shiftSize - 1) | 373 mask = 1 << (shiftSize - 1) |
369 return '\n\t{dst} = ({a} >> {b}) | ({a} & {mask}'.format(a = params[0], b = params[1], dst = params[2], mask = mask) | 374 return '\n\t{dst} = ({a} >> {b}) | ({a} & {mask});'.format(a = params[0], b = params[1], dst = params[2], mask = mask) |
370 | 375 |
371 _opMap = { | 376 _opMap = { |
372 'mov': Op(lambda val: val).cUnaryOperator(''), | 377 'mov': Op(lambda val: val).cUnaryOperator(''), |
373 'not': Op(lambda val: ~val).cUnaryOperator('~'), | 378 'not': Op(lambda val: ~val).cUnaryOperator('~'), |
374 'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'), | 379 'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'), |
379 'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'), | 384 'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'), |
380 'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl), | 385 'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl), |
381 'and': Op(lambda a, b: a & b).cBinaryOperator('&'), | 386 'and': Op(lambda a, b: a & b).cBinaryOperator('&'), |
382 'or': Op(lambda a, b: a | b).cBinaryOperator('|'), | 387 'or': Op(lambda a, b: a | b).cBinaryOperator('|'), |
383 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'), | 388 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'), |
389 'abs': Op(lambda val: abs(val)).addImplementation( | |
390 'c', 1, lambda prog, params: '\n\t{dst} = abs({src});'.format(dst=params[1], src=params[0]) | |
391 ), | |
384 'cmp': Op().addImplementation('c', None, _cmpCImpl), | 392 'cmp': Op().addImplementation('c', None, _cmpCImpl), |
385 'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format( | 393 'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format( |
386 pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]]) | 394 pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]]) |
387 )), | 395 )), |
388 'cycles': Op().addImplementation('c', None, | 396 'cycles': Op().addImplementation('c', None, |
389 lambda prog, params: '\n\tcontext->current_cycle += context->opts->gen.clock_divider * {0};'.format( | 397 lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format( |
390 params[0] | 398 params[0] |
391 ) | 399 ) |
392 ), | 400 ), |
393 'addsize': Op( | 401 'addsize': Op( |
394 lambda a, b: b + (2 * a if a else 1) | 402 lambda a, b: b + (2 * a if a else 1) |
395 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + {sz} ? {sz} * 2 : 1;'.format( | 403 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + {sz} ? {sz} * 2 : 1;'.format( |
396 dst = params[1], sz = params[0], val = params[1] | 404 dst = params[2], sz = params[0], val = params[1] |
397 )), | 405 )), |
398 'decsize': Op( | 406 'decsize': Op( |
399 lambda a, b: b - (2 * a if a else 1) | 407 lambda a, b: b - (2 * a if a else 1) |
400 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - {sz} ? {sz} * 2 : 1;'.format( | 408 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - {sz} ? {sz} * 2 : 1;'.format( |
401 dst = params[2], sz = params[0], val = params[1] | 409 dst = params[2], sz = params[0], val = params[1] |
507 if name in self.current_locals: | 515 if name in self.current_locals: |
508 return self.current_locals[name] | 516 return self.current_locals[name] |
509 return self.parent.localSize(name) | 517 return self.parent.localSize(name) |
510 | 518 |
511 def generate(self, prog, parent, fieldVals, output, otype): | 519 def generate(self, prog, parent, fieldVals, output, otype): |
512 oldScope = prog.currentScope | 520 prog.pushScope(self) |
513 prog.currentScope = self | |
514 param = prog.resolveParam(self.param, parent, fieldVals) | 521 param = prog.resolveParam(self.param, parent, fieldVals) |
515 if type(param) is int: | 522 if type(param) is int: |
516 self.regValues = self.parent.regValues | 523 self.regValues = self.parent.regValues |
517 if param in self.cases: | 524 if param in self.cases: |
518 if self.case_locals[param]: | 525 self.current_locals = self.case_locals[param] |
519 output.append('\n\t{') | 526 output.append('\n\t{') |
520 for local in self.case_locals[param]: | 527 for local in self.case_locals[param]: |
521 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local)) | 528 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local)) |
522 for op in self.cases[param]: | 529 for op in self.cases[param]: |
523 op.generate(prog, self, fieldVals, output, otype) | 530 op.generate(prog, self, fieldVals, output, otype) |
524 if self.case_locals[param]: | 531 output.append('\n\t}') |
525 output.append('\n\t}') | |
526 elif self.default: | 532 elif self.default: |
527 if self.default_locals: | 533 self.current_locals = self.default_locals |
528 output.append('\n\t{') | 534 output.append('\n\t{') |
529 for local in self.default: | 535 for local in self.default_locals: |
530 output.append('\n\tuint{0}_t {1};'.format(self.default[local], local)) | 536 output.append('\n\tuint{0}_t {1};'.format(self.default[local], local)) |
531 for op in self.default: | 537 for op in self.default: |
532 op.generate(prog, self, fieldVals, output, otype) | 538 op.generate(prog, self, fieldVals, output, otype) |
539 output.append('\n\t}') | |
533 else: | 540 else: |
534 output.append('\n\tswitch(' + param + ')') | 541 output.append('\n\tswitch(' + param + ')') |
535 output.append('\n\t{') | 542 output.append('\n\t{') |
536 for case in self.cases: | 543 for case in self.cases: |
544 self.current_locals = self.case_locals[case] | |
537 self.regValues = dict(self.parent.regValues) | 545 self.regValues = dict(self.parent.regValues) |
538 output.append('\n\tcase {0}: '.format(case) + '{') | 546 output.append('\n\tcase {0}: '.format(case) + '{') |
539 for local in self.case_locals[case]: | 547 for local in self.case_locals[case]: |
540 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[case][local], local)) | 548 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[case][local], local)) |
541 for op in self.cases[case]: | 549 for op in self.cases[case]: |
542 op.generate(prog, self, fieldVals, output, otype) | 550 op.generate(prog, self, fieldVals, output, otype) |
543 output.append('\n\tbreak;') | 551 output.append('\n\tbreak;') |
544 output.append('\n\t}') | 552 output.append('\n\t}') |
545 if self.default: | 553 if self.default: |
554 self.current_locals = self.default_locals | |
546 self.regValues = dict(self.parent.regValues) | 555 self.regValues = dict(self.parent.regValues) |
547 output.append('\n\tdefault: {') | 556 output.append('\n\tdefault: {') |
548 for local in self.default_locals: | 557 for local in self.default_locals: |
549 output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local)) | 558 output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local)) |
550 for op in self.default: | 559 for op in self.default: |
551 op.generate(prog, self, fieldVals, output, otype) | 560 op.generate(prog, self, fieldVals, output, otype) |
552 output.append('\n\t}') | 561 output.append('\n\t}') |
553 prog.currentScope = oldScope | 562 prog.popScope() |
554 | 563 |
555 def __str__(self): | 564 def __str__(self): |
556 keys = self.cases.keys() | 565 keys = self.cases.keys() |
557 keys.sort() | 566 keys.sort() |
558 lines = ['\n\tswitch'] | 567 lines = ['\n\tswitch'] |
607 return self.curLocals.get(name) | 616 return self.curLocals.get(name) |
608 | 617 |
609 def resolveLocal(self, name): | 618 def resolveLocal(self, name): |
610 if name in self.locals: | 619 if name in self.locals: |
611 return name | 620 return name |
612 return None | 621 return self.parent.resolveLocal(name) |
613 | 622 |
614 def _genTrueBody(self): | 623 def _genTrueBody(self, prog, fieldVals, output, otype): |
615 self.curLocals = self.locals | 624 self.curLocals = self.locals |
625 for local in self.locals: | |
626 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.locals[local], nm=local)) | |
616 for op in self.body: | 627 for op in self.body: |
617 op.generate(prog, self, fieldVals, output, otype) | 628 op.generate(prog, self, fieldVals, output, otype) |
618 | 629 |
619 def _genFalseBody(self): | 630 def _genFalseBody(self, prog, fieldVals, output, otype): |
620 self.curLocals = self.elseLocals | 631 self.curLocals = self.elseLocals |
621 for op in self.body: | 632 for local in self.elseLocals: |
633 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.elseLocals[local], nm=local)) | |
634 for op in self.elseBody: | |
622 op.generate(prog, self, fieldVals, output, otype) | 635 op.generate(prog, self, fieldVals, output, otype) |
623 | 636 |
624 def _genConstParam(self, param): | 637 def _genConstParam(self, param, prog, fieldVals, output, otype): |
625 if param: | 638 if param: |
626 self._genTrueBody() | 639 self._genTrueBody(prog, fieldVals, output, otype) |
627 else: | 640 else: |
628 self._genFalseBody() | 641 self._genFalseBody(prog, fieldVals, output, otype) |
629 | 642 |
630 def generate(self, prog, parent, fieldVals, output, otype): | 643 def generate(self, prog, parent, fieldVals, output, otype): |
631 self.regValues = parent.regValues | 644 self.regValues = parent.regValues |
632 try: | 645 try: |
633 self._genConstParam(prog.checkBool(self.cond)) | 646 self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype) |
634 except Exception: | 647 except Exception: |
635 if self.cond in _ifCmpImpl[otype]: | 648 if self.cond in _ifCmpImpl[otype]: |
636 output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output)) | 649 output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output)) |
637 for op in self.body: | 650 self._genTrueBody(prog, fieldVals, output, otype) |
638 op.generate(prog, self, fieldVals, output, otype) | |
639 if self.elseBody: | 651 if self.elseBody: |
640 output.append('\n\t} else {') | 652 output.append('\n\t} else {') |
641 for op in self.elseBody: | 653 self._genFalseBody(prog, fieldVals, output, otype) |
642 op.generate(prog, self, fieldVals, output, otype) | |
643 output.append('\n\t}') | 654 output.append('\n\t}') |
644 else: | 655 else: |
645 cond = prog.resolveParam(self.cond, parent, fieldVals) | 656 cond = prog.resolveParam(self.cond, parent, fieldVals) |
646 if type(cond) is int: | 657 if type(cond) is int: |
647 if cond: | 658 self._genConstParam(cond, prog, fieldVals, output, otype) |
648 for op in self.body: | |
649 op.generate(prog, self, fieldVals, output, otype) | |
650 else: | |
651 for op in self.elseBody: | |
652 op.generate(prog, self, fieldVals, output, otype) | |
653 else: | 659 else: |
654 output.append('\n\tif ({cond}) '.format(cond=cond) + '{') | 660 output.append('\n\tif ({cond}) '.format(cond=cond) + '{') |
655 for op in self.body: | 661 self._genTrueBody(prog, fieldVals, output, otype) |
656 op.generate(prog, self, fieldVals, output, otype) | |
657 if self.elseBody: | 662 if self.elseBody: |
658 output.append('\n\t} else {') | 663 output.append('\n\t} else {') |
659 for op in self.elseBody: | 664 self._genFalseBody(prog, fieldVals, output, otype) |
660 op.generate(prog, self, fieldVals, output, otype) | |
661 output.append('\n\t}') | 665 output.append('\n\t}') |
662 | 666 |
663 | 667 |
664 def __str__(self): | 668 def __str__(self): |
665 lines = ['\n\tif'] | 669 lines = ['\n\tif'] |
716 elif len(parts) > 2: | 720 elif len(parts) > 2: |
717 self.addRegArray(parts[0], int(parts[1]), parts[2:]) | 721 self.addRegArray(parts[0], int(parts[1]), parts[2:]) |
718 else: | 722 else: |
719 self.addReg(parts[0], int(parts[1])) | 723 self.addReg(parts[0], int(parts[1])) |
720 return self | 724 return self |
725 | |
726 def writeHeader(self, otype, hFile): | |
727 fieldList = [] | |
728 for reg in self.regs: | |
729 if not self.isRegArrayMember(reg): | |
730 fieldList.append((self.regs[reg], 1, reg)) | |
731 for arr in self.regArrays: | |
732 size,regs = self.regArrays[arr] | |
733 if not type(regs) is int: | |
734 regs = len(regs) | |
735 fieldList.append((size, regs, arr)) | |
736 fieldList.sort() | |
737 fieldList.reverse() | |
738 for size, count, name in fieldList: | |
739 if count > 1: | |
740 hFile.write('\n\tuint{sz}_t {nm}[{ct}];'.format(sz=size, nm=name, ct=count)) | |
741 else: | |
742 hFile.write('\n\tuint{sz}_t {nm};'.format(sz=size, nm=name)) | |
721 | 743 |
722 class Flags: | 744 class Flags: |
723 def __init__(self): | 745 def __init__(self): |
724 self.flagBits = {} | 746 self.flagBits = {} |
725 self.flagCalc = {} | 747 self.flagCalc = {} |
752 raise Exception('Undefined flag ' + flag) | 774 raise Exception('Undefined flag ' + flag) |
753 loc,_,bit = self.flagStorage[flag].partition('.') | 775 loc,_,bit = self.flagStorage[flag].partition('.') |
754 if bit: | 776 if bit: |
755 return (loc, int(bit)) | 777 return (loc, int(bit)) |
756 else: | 778 else: |
757 return loc | 779 return loc |
758 | 780 |
759 def disperseFlags(self, prog, otype): | 781 def disperseFlags(self, prog, otype): |
760 bitToFlag = [None] * (self.maxBit+1) | 782 bitToFlag = [None] * (self.maxBit+1) |
761 src = prog.resolveReg(self.flagReg, None, {}) | 783 src = prog.resolveReg(self.flagReg, None, {}) |
762 output = [] | 784 output = [] |
870 self.extra_tables = info.get('extra_tables', []) | 892 self.extra_tables = info.get('extra_tables', []) |
871 self.context_type = self.prefix + 'context' | 893 self.context_type = self.prefix + 'context' |
872 self.body = info.get('body', [None])[0] | 894 self.body = info.get('body', [None])[0] |
873 self.flags = flags | 895 self.flags = flags |
874 self.lastDst = None | 896 self.lastDst = None |
897 self.scopes = [] | |
875 self.currentScope = None | 898 self.currentScope = None |
876 self.lastOp = None | 899 self.lastOp = None |
877 | 900 |
878 def __str__(self): | 901 def __str__(self): |
879 pieces = [] | 902 pieces = [] |
883 pieces.append('\n'+str(self.subroutines[name])) | 906 pieces.append('\n'+str(self.subroutines[name])) |
884 for instruction in self.instructions: | 907 for instruction in self.instructions: |
885 pieces.append('\n'+str(instruction)) | 908 pieces.append('\n'+str(instruction)) |
886 return ''.join(pieces) | 909 return ''.join(pieces) |
887 | 910 |
911 def writeHeader(self, otype, header): | |
912 hFile = open(header, 'w') | |
913 macro = header.upper().replace('.', '_') | |
914 hFile.write('#ifndef {0}_'.format(macro)) | |
915 hFile.write('\n#define {0}_'.format(macro)) | |
916 hFile.write('\n#include "backend.h"') | |
917 hFile.write('\n\ntypedef struct {') | |
918 hFile.write('\n\tcpu_options gen;') | |
919 hFile.write('\n}} {0}options;'.format(self.prefix)) | |
920 hFile.write('\n\ntypedef struct {') | |
921 hFile.write('\n\t{0}options *opts;'.format(self.prefix)) | |
922 hFile.write('\n\tuint32_t cycles;') | |
923 self.regs.writeHeader(otype, hFile) | |
924 hFile.write('\n}} {0}context;'.format(self.prefix)) | |
925 hFile.write('\n') | |
926 hFile.write('\n#endif //{0}_'.format(macro)) | |
927 hFile.write('\n') | |
928 hFile.close() | |
888 def build(self, otype): | 929 def build(self, otype): |
889 body = [] | 930 body = [] |
890 pieces = [] | 931 pieces = [] |
891 for table in self.instructions: | 932 for table in self.instructions: |
892 opmap = [None] * (1 << self.opsize) | 933 opmap = [None] * (1 << self.opsize) |
902 self.needFlagDisperse = False | 943 self.needFlagDisperse = False |
903 self.lastOp = None | 944 self.lastOp = None |
904 opmap[val] = inst.generateName(val) | 945 opmap[val] = inst.generateName(val) |
905 bodymap[val] = inst.generateBody(val, self, otype) | 946 bodymap[val] = inst.generateBody(val, self, otype) |
906 | 947 |
907 pieces.append('\nstatic void *impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap))) | 948 pieces.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix)) |
949 pieces.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap))) | |
908 for inst in range(0, len(opmap)): | 950 for inst in range(0, len(opmap)): |
909 op = opmap[inst] | 951 op = opmap[inst] |
910 if op is None: | 952 if op is None: |
911 pieces.append('\n\tunimplemented,') | 953 pieces.append('\n\tunimplemented,') |
912 else: | 954 else: |
914 body.append(bodymap[inst]) | 956 body.append(bodymap[inst]) |
915 pieces.append('\n};') | 957 pieces.append('\n};') |
916 if self.body in self.subroutines: | 958 if self.body in self.subroutines: |
917 pieces.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type)) | 959 pieces.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type)) |
918 pieces.append('\n{') | 960 pieces.append('\n{') |
919 pieces.append('\n\twhile (context->current_cycle < target_cycle)') | 961 pieces.append('\n\twhile (context->cycles < target_cycle)') |
920 pieces.append('\n\t{') | 962 pieces.append('\n\t{') |
921 self.meta = {} | 963 self.meta = {} |
922 self.temp = {} | 964 self.temp = {} |
923 self.subroutines[self.body].inline(self, [], pieces, otype, None) | 965 self.subroutines[self.body].inline(self, [], pieces, otype, None) |
924 pieces.append('\n\t}') | 966 pieces.append('\n\t}') |
925 pieces.append('\n}') | 967 pieces.append('\n}') |
968 body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix)) | |
969 body.append('\n{') | |
970 body.append('\n\tfatal_error("Unimplemented instruction");') | |
971 body.append('\n}\n') | |
926 return ''.join(body) + ''.join(pieces) | 972 return ''.join(body) + ''.join(pieces) |
927 | 973 |
928 def checkBool(self, name): | 974 def checkBool(self, name): |
929 if not name in self.booleans: | 975 if not name in self.booleans: |
930 raise Exception(name + ' is not a defined boolean flag') | 976 raise Exception(name + ' is not a defined boolean flag') |
1018 if sep and self.regs.isRegArray(begin): | 1064 if sep and self.regs.isRegArray(begin): |
1019 return self.regs.regArrays[begin][0] | 1065 return self.regs.regArrays[begin][0] |
1020 if self.regs.isReg(name): | 1066 if self.regs.isReg(name): |
1021 return self.regs.regs[name] | 1067 return self.regs.regs[name] |
1022 return 32 | 1068 return 32 |
1069 | |
1070 def pushScope(self, scope): | |
1071 self.scopes.append(scope) | |
1072 self.currentScope = scope | |
1073 | |
1074 def popScope(self): | |
1075 ret = self.scopes.pop() | |
1076 self.currentScope = self.scopes[-1] if self.scopes else None | |
1077 return ret | |
1078 | |
1079 def getRootScope(self): | |
1080 return self.scopes[0] | |
1023 | 1081 |
1024 def parse(f): | 1082 def parse(f): |
1025 instructions = {} | 1083 instructions = {} |
1026 subroutines = {} | 1084 subroutines = {} |
1027 registers = None | 1085 registers = None |
1105 else: | 1163 else: |
1106 p = Program(registers, instructions, subroutines, info, flags) | 1164 p = Program(registers, instructions, subroutines, info, flags) |
1107 p.booleans['dynarec'] = False | 1165 p.booleans['dynarec'] = False |
1108 p.booleans['interp'] = True | 1166 p.booleans['interp'] = True |
1109 | 1167 |
1110 print('#include "m68k_prefix.c"') | 1168 if 'header' in info: |
1169 print('#include "{0}"'.format(info['header'][0])) | |
1170 p.writeHeader('c', info['header'][0]) | |
1171 print('#include "util.h"') | |
1172 print('#include <stdlib.h>') | |
1111 print(p.build('c')) | 1173 print(p.build('c')) |
1112 | 1174 |
1113 def main(argv): | 1175 def main(argv): |
1114 f = open(argv[1]) | 1176 f = open(argv[1]) |
1115 parse(f) | 1177 parse(f) |