Mercurial > repos > blastem
comparison 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 |
comparison
equal
deleted
inserted
replaced
1837:f6ee0df6bb48 | 1838:0c1491818f4b |
---|---|
46 self.implementation = [] | 46 self.implementation = [] |
47 self.locals = {} | 47 self.locals = {} |
48 self.regValues = {} | 48 self.regValues = {} |
49 self.varyingBits = 0 | 49 self.varyingBits = 0 |
50 self.invalidFieldValues = {} | 50 self.invalidFieldValues = {} |
51 self.invalidCombos = [] | |
51 self.newLocals = [] | 52 self.newLocals = [] |
52 for field in fields: | 53 for field in fields: |
53 self.varyingBits += fields[field][1] | 54 self.varyingBits += fields[field][1] |
54 | 55 |
55 def addOp(self, op): | 56 def addOp(self, op): |
56 if op.op == 'local': | 57 if op.op == 'local': |
57 name = op.params[0] | 58 name = op.params[0] |
58 size = int(op.params[1]) | 59 size = int(op.params[1]) |
59 self.locals[name] = size | 60 self.locals[name] = size |
60 elif op.op == 'invalid': | 61 elif op.op == 'invalid': |
61 name = op.params[0] | 62 if len(op.params) < 3: |
62 value = int(op.params[1]) | 63 name = op.params[0] |
63 self.invalidFieldValues.setdefault(name, set()).add(value) | 64 value = int(op.params[1]) |
65 self.invalidFieldValues.setdefault(name, set()).add(value) | |
66 else: | |
67 vmap = {} | |
68 for i in range(0, len(op.params), 2): | |
69 name = op.params[i] | |
70 value = int(op.params[i+1]) | |
71 vmap[name] = value | |
72 self.invalidCombos.append(vmap) | |
64 else: | 73 else: |
65 self.implementation.append(op) | 74 self.implementation.append(op) |
66 | 75 |
67 def resolveLocal(self, name): | 76 def resolveLocal(self, name): |
68 if name in self.locals: | 77 if name in self.locals: |
87 def allValues(self): | 96 def allValues(self): |
88 values = [] | 97 values = [] |
89 for i in range(0, 1 << self.varyingBits): | 98 for i in range(0, 1 << self.varyingBits): |
90 iword = self.value | 99 iword = self.value |
91 doIt = True | 100 doIt = True |
101 combos = [] | |
102 for combo in self.invalidCombos: | |
103 combos.append(dict(combo)) | |
92 for field in self.fields: | 104 for field in self.fields: |
93 shift,bits = self.fields[field] | 105 shift,bits = self.fields[field] |
94 val = i & ((1 << bits) - 1) | 106 val = i & ((1 << bits) - 1) |
95 if field in self.invalidFieldValues and val in self.invalidFieldValues[field]: | 107 if field in self.invalidFieldValues and val in self.invalidFieldValues[field]: |
96 doIt = False | 108 doIt = False |
109 break | |
110 nextcombos = [] | |
111 for combo in combos: | |
112 if field in combo: | |
113 if combo[field] == val: | |
114 del combo[field] | |
115 if not combo: | |
116 doIt = False | |
117 break | |
118 else: | |
119 continue | |
120 nextcombos.append(combo) | |
121 combos = nextcombos | |
122 if not doIt: | |
97 break | 123 break |
98 i >>= bits | 124 i >>= bits |
99 iword |= val << shift | 125 iword |= val << shift |
100 if doIt: | 126 if doIt: |
101 values.append(iword) | 127 values.append(iword) |
130 self.newLocals = [] | 156 self.newLocals = [] |
131 fieldVals,_ = self.getFieldVals(value) | 157 fieldVals,_ = self.getFieldVals(value) |
132 self.processOps(prog, fieldVals, output, otype, self.implementation) | 158 self.processOps(prog, fieldVals, output, otype, self.implementation) |
133 | 159 |
134 if prog.dispatch == 'call': | 160 if prog.dispatch == 'call': |
135 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{' | 161 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context, uint32_t target_cycle)\n{' |
136 elif prog.dispatch == 'goto': | 162 elif prog.dispatch == 'goto': |
137 begin = '\n' + self.generateName(value) + ': {' | 163 begin = '\n' + self.generateName(value) + ': {' |
138 else: | 164 else: |
139 raise Exception('Unsupported dispatch type ' + prog.dispatch) | 165 raise Exception('Unsupported dispatch type ' + prog.dispatch) |
140 if prog.needFlagCoalesce: | 166 if prog.needFlagCoalesce: |
141 begin += prog.flags.coalesceFlags(prog, otype) | 167 begin += prog.flags.coalesceFlags(prog, otype) |
142 if prog.needFlagDisperse: | 168 if prog.needFlagDisperse: |
143 output.append(prog.flags.disperseFlags(prog, otype)) | 169 output.append(prog.flags.disperseFlags(prog, otype)) |
144 for var in self.newLocals: | 170 for var in self.newLocals: |
145 begin += '\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var) | 171 begin += '\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var) |
172 for size in prog.temp: | |
173 begin += '\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size) | |
146 prog.popScope() | 174 prog.popScope() |
147 if prog.dispatch == 'goto': | 175 if prog.dispatch == 'goto': |
148 output += prog.nextInstruction(otype) | 176 output += prog.nextInstruction(otype) |
149 return begin + ''.join(output) + '\n}' | 177 return begin + ''.join(output) + '\n}' |
150 | 178 |
235 a = params[1] | 263 a = params[1] |
236 b = params[0] | 264 b = params[0] |
237 else: | 265 else: |
238 a = params[0] | 266 a = params[0] |
239 b = params[1] | 267 b = params[1] |
268 needsSizeAdjust = False | |
269 if len(params) > 3: | |
270 size = params[3] | |
271 if size == 0: | |
272 size = 8 | |
273 elif size == 1: | |
274 size = 16 | |
275 else: | |
276 size = 32 | |
277 prog.lastSize = size | |
278 destSize = prog.paramSize(rawParams[2]) | |
279 if destSize > size: | |
280 needsSizeAdjust = True | |
281 prog.sizeAdjust = size | |
240 needsCarry = needsOflow = needsHalf = False | 282 needsCarry = needsOflow = needsHalf = False |
241 if flagUpdates: | 283 if flagUpdates: |
242 for flag in flagUpdates: | 284 for flag in flagUpdates: |
243 calc = prog.flags.flagCalc[flag] | 285 calc = prog.flags.flagCalc[flag] |
244 if calc == 'carry': | 286 if calc == 'carry': |
246 elif calc == 'half-carry': | 288 elif calc == 'half-carry': |
247 needsHalf = True | 289 needsHalf = True |
248 elif calc == 'overflow': | 290 elif calc == 'overflow': |
249 needsOflow = True | 291 needsOflow = True |
250 decl = '' | 292 decl = '' |
251 if needsCarry or needsOflow or needsHalf: | 293 if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust): |
252 size = prog.paramSize(rawParams[2]) | 294 if len(params) <= 3: |
295 size = prog.paramSize(rawParams[2]) | |
253 if needsCarry and op != 'lsr': | 296 if needsCarry and op != 'lsr': |
254 size *= 2 | 297 size *= 2 |
255 decl,name = prog.getTemp(size) | 298 decl,name = prog.getTemp(size) |
256 dst = prog.carryFlowDst = name | 299 dst = prog.carryFlowDst = name |
257 prog.lastA = a | 300 prog.lastA = a |
258 prog.lastB = b | 301 prog.lastB = b |
302 if size == 64: | |
303 a = '((uint64_t){a})'.format(a=a) | |
304 b = '((uint64_t){b})'.format(b=b) | |
259 prog.lastBFlow = b if op == '-' else '(~{b})'.format(b=b) | 305 prog.lastBFlow = b if op == '-' else '(~{b})'.format(b=b) |
260 else: | 306 elif needsSizeAdjust: |
307 decl,name = prog.getTemp(size) | |
261 dst = params[2] | 308 dst = params[2] |
262 return decl + '\n\t{dst} = {a} {op} {b};'.format( | 309 return '{decl}\n\t{tmp} = ({a} & {mask}) {op} ({b} & {mask});\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format( |
263 dst = dst, a = a, b = b, op = op | 310 decl = decl, tmp = name, a = a, b = b, op = op, dst = dst, mask = ((1 << size) - 1) |
264 ) | 311 ) |
312 else: | |
313 dst = params[2] | |
314 if needsSizeAdjust: | |
315 return decl + '\n\t{dst} = ({a} & {mask}) {op} ({b} & {mask});'.format( | |
316 dst = dst, a = a, b = b, op = op, mask = (1 << prog.sizeAdjust) - 1 | |
317 ) | |
318 else: | |
319 return decl + '\n\t{dst} = {a} {op} {b};'.format( | |
320 dst = dst, a = a, b = b, op = op | |
321 ) | |
265 self.impls['c'] = _impl | 322 self.impls['c'] = _impl |
266 self.outOp = (2,) | 323 self.outOp = (2,) |
267 return self | 324 return self |
268 def cUnaryOperator(self, op): | 325 def cUnaryOperator(self, op): |
269 def _impl(prog, params, rawParams, flagUpdates): | 326 def _impl(prog, params, rawParams, flagUpdates): |
270 dst = params[1] | 327 dst = params[1] |
271 decl = '' | 328 decl = '' |
329 needsSizeAdjust = False | |
330 if len(params) > 2: | |
331 size = params[2] | |
332 if size == 0: | |
333 size = 8 | |
334 elif size == 1: | |
335 size = 16 | |
336 else: | |
337 size = 32 | |
338 prog.lastSize = size | |
339 destSize = prog.paramSize(rawParams[1]) | |
340 if destSize > size: | |
341 needsSizeAdjust = True | |
342 prog.sizeAdjust = size | |
272 if op == '-': | 343 if op == '-': |
273 if flagUpdates: | 344 if flagUpdates: |
274 for flag in flagUpdates: | 345 for flag in flagUpdates: |
275 calc = prog.flags.flagCalc[flag] | 346 calc = prog.flags.flagCalc[flag] |
276 if calc == 'carry': | 347 if calc == 'carry': |
277 needsCarry = True | 348 needsCarry = True |
278 elif calc == 'half-carry': | 349 elif calc == 'half-carry': |
279 needsHalf = True | 350 needsHalf = True |
280 elif calc == 'overflow': | 351 elif calc == 'overflow': |
281 needsOflow = True | 352 needsOflow = True |
282 if needsCarry or needsOflow or needsHalf: | 353 if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust): |
283 size = prog.paramSize(rawParams[1]) | 354 size = prog.paramSize(rawParams[1]) |
284 if needsCarry: | 355 if needsCarry: |
285 size *= 2 | 356 size *= 2 |
286 decl,name = prog.getTemp(size) | 357 decl,name = prog.getTemp(size) |
287 dst = prog.carryFlowDst = name | 358 dst = prog.carryFlowDst = name |
288 prog.lastA = 0 | 359 prog.lastA = 0 |
289 prog.lastB = params[0] | 360 prog.lastB = params[0] |
290 prog.lastBFlow = params[0] | 361 prog.lastBFlow = params[0] |
291 return decl + '\n\t{dst} = {op}{a};'.format( | 362 if needsSizeAdjust: |
292 dst = dst, a = params[0], op = op | 363 return decl + '\n\t{dst} = ({dst} & ~{mask}) | (({op}{a}) & {mask});'.format( |
293 ) | 364 dst = dst, a = params[0], op = op, mask = (1 << prog.sizeAdjust) - 1 |
365 ) | |
366 else: | |
367 return decl + '\n\t{dst} = {op}{a};'.format( | |
368 dst = dst, a = params[0], op = op | |
369 ) | |
294 self.impls['c'] = _impl | 370 self.impls['c'] = _impl |
295 self.outOp = (1,) | 371 self.outOp = (1,) |
296 return self | 372 return self |
297 def addImplementation(self, lang, outOp, impl): | 373 def addImplementation(self, lang, outOp, impl): |
298 self.impls[lang] = impl | 374 self.impls[lang] = impl |
334 if len(params) == 1: | 410 if len(params) == 1: |
335 table = 'main' | 411 table = 'main' |
336 else: | 412 else: |
337 table = params[1] | 413 table = params[1] |
338 if prog.dispatch == 'call': | 414 if prog.dispatch == 'call': |
339 return '\n\timpl_{tbl}[{op}](context);'.format(tbl = table, op = params[0]) | 415 return '\n\timpl_{tbl}[{op}](context, target_cycle);'.format(tbl = table, op = params[0]) |
340 elif prog.dispatch == 'goto': | 416 elif prog.dispatch == 'goto': |
341 return '\n\tgoto *impl_{tbl}[{op}];'.format(tbl = table, op = params[0]) | 417 return '\n\tgoto *impl_{tbl}[{op}];'.format(tbl = table, op = params[0]) |
342 else: | 418 else: |
343 raise Exception('Unsupported dispatch type ' + prog.dispatch) | 419 raise Exception('Unsupported dispatch type ' + prog.dispatch) |
344 | 420 |
356 lastDst = prog.resolveParam(prog.lastDst, prog.currentScope, {}) | 432 lastDst = prog.resolveParam(prog.lastDst, prog.currentScope, {}) |
357 storage = prog.flags.getStorage(flag) | 433 storage = prog.flags.getStorage(flag) |
358 if calc == 'bit' or calc == 'sign' or calc == 'carry' or calc == 'half' or calc == 'overflow': | 434 if calc == 'bit' or calc == 'sign' or calc == 'carry' or calc == 'half' or calc == 'overflow': |
359 myRes = lastDst | 435 myRes = lastDst |
360 if calc == 'sign': | 436 if calc == 'sign': |
361 resultBit = prog.paramSize(prog.lastDst) - 1 | 437 resultBit = prog.getLastSize() - 1 |
362 elif calc == 'carry': | 438 elif calc == 'carry': |
363 if prog.lastOp.op in ('asr', 'lsr'): | 439 if prog.lastOp.op in ('asr', 'lsr'): |
364 resultBit = 0 | 440 resultBit = 0 |
365 myRes = prog.lastA | 441 myRes = prog.lastA |
366 else: | 442 else: |
367 resultBit = prog.paramSize(prog.lastDst) | 443 resultBit = prog.getLastSize() |
368 if prog.lastOp.op == 'ror': | 444 if prog.lastOp.op == 'ror': |
369 resultBit -= 1 | 445 resultBit -= 1 |
370 elif calc == 'half': | 446 elif calc == 'half': |
371 resultBit = prog.paramSize(prog.lastDst) - 4 | 447 resultBit = prog.getLastSize() - 4 |
372 myRes = '({a} ^ {b} ^ {res})'.format(a = prog.lastA, b = prog.lastB, res = lastDst) | 448 myRes = '({a} ^ {b} ^ {res})'.format(a = prog.lastA, b = prog.lastB, res = lastDst) |
373 elif calc == 'overflow': | 449 elif calc == 'overflow': |
374 resultBit = prog.paramSize(prog.lastDst) - 1 | 450 resultBit = prog.getLastSize() - 1 |
375 myRes = '((({a} ^ {b})) & ({a} ^ {res}))'.format(a = prog.lastA, b = prog.lastBFlow, res = lastDst) | 451 myRes = '((({a} ^ {b})) & ({a} ^ {res}))'.format(a = prog.lastA, b = prog.lastBFlow, res = lastDst) |
376 else: | 452 else: |
377 #Note: offsetting this by the operation size - 8 makes sense for the Z80 | 453 #Note: offsetting this by the operation size - 8 makes sense for the Z80 |
378 #but might not for other CPUs with this kind of fixed bit flag behavior | 454 #but might not for other CPUs with this kind of fixed bit flag behavior |
379 resultBit = int(resultBit) + prog.paramSize(prog.lastDst) - 8 | 455 resultBit = int(resultBit) + prog.getLastSize() - 8 |
380 if type(storage) is tuple: | 456 if type(storage) is tuple: |
381 reg,storageBit = storage | 457 reg,storageBit = storage |
382 if storageBit == resultBit: | 458 if storageBit == resultBit: |
383 directFlags.setdefault((reg, myRes), []).append(resultBit) | 459 directFlags.setdefault((reg, myRes), []).append(resultBit) |
384 else: | 460 else: |
399 output.append('\n\t{reg} = {res} >> {shift} & {mask}U;'.format(reg=reg, res=myRes, shift = resultBit - maxBit, mask = 1 << maxBit)) | 475 output.append('\n\t{reg} = {res} >> {shift} & {mask}U;'.format(reg=reg, res=myRes, shift = resultBit - maxBit, mask = 1 << maxBit)) |
400 else: | 476 else: |
401 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit)) | 477 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit)) |
402 elif calc == 'zero': | 478 elif calc == 'zero': |
403 if prog.carryFlowDst: | 479 if prog.carryFlowDst: |
404 realSize = prog.paramSize(prog.lastDst) | 480 realSize = prog.getLastSize() |
405 if realSize != prog.paramSize(prog.carryFlowDst): | 481 if realSize != prog.paramSize(prog.carryFlowDst): |
406 lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1) | 482 lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1) |
407 if type(storage) is tuple: | 483 if type(storage) is tuple: |
408 reg,storageBit = storage | 484 reg,storageBit = storage |
409 reg = prog.resolveParam(reg, None, {}) | 485 reg = prog.resolveParam(reg, None, {}) |
415 output.append('\n\t{reg} = {res} == 0;'.format( | 491 output.append('\n\t{reg} = {res} == 0;'.format( |
416 reg = reg, res = lastDst | 492 reg = reg, res = lastDst |
417 )) | 493 )) |
418 elif calc == 'parity': | 494 elif calc == 'parity': |
419 parity = storage | 495 parity = storage |
420 paritySize = prog.paramSize(prog.lastDst) | 496 paritySize = prog.getLastSize() |
421 if prog.carryFlowDst: | 497 if prog.carryFlowDst: |
422 parityDst = paritySrc = prog.carryFlowDst | 498 parityDst = paritySrc = prog.carryFlowDst |
423 else: | 499 else: |
424 paritySrc = lastDst | 500 paritySrc = lastDst |
425 decl,name = prog.getTemp(paritySize) | 501 decl,name = prog.getTemp(paritySize) |
439 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format( | 515 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format( |
440 reg = resolved, mask = mask, res = myRes | 516 reg = resolved, mask = mask, res = myRes |
441 )) | 517 )) |
442 if prog.carryFlowDst: | 518 if prog.carryFlowDst: |
443 if prog.lastOp.op != 'cmp': | 519 if prog.lastOp.op != 'cmp': |
444 output.append('\n\t{dst} = {tmpdst};'.format(dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst)) | 520 if prog.sizeAdjust: |
521 output.append('\n\t{dst} = ({dst} & ~{mask}) | ({tmpdst} & {mask});'.format( | |
522 dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst, mask = ((1 << prog.sizeAdjust) - 1) | |
523 )) | |
524 prog.sizeAdjust = None | |
525 else: | |
526 output.append('\n\t{dst} = {tmpdst};'.format(dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst)) | |
445 prog.carryFlowDst = None | 527 prog.carryFlowDst = None |
446 if parity: | 528 if parity: |
447 if paritySize > 8: | 529 if paritySize > 8: |
448 if paritySize > 16: | 530 if paritySize > 16: |
449 output.append('\n\t{dst} = {src} ^ ({src} >> 16);'.format(dst=parityDst, src=paritySrc)) | 531 output.append('\n\t{dst} = {src} ^ ({src} >> 16);'.format(dst=parityDst, src=paritySrc)) |
498 prog.lastBFlow = params[0] | 580 prog.lastBFlow = params[0] |
499 scope = prog.getRootScope() | 581 scope = prog.getRootScope() |
500 if not scope.resolveLocal(tmpvar): | 582 if not scope.resolveLocal(tmpvar): |
501 scope.addLocal(tmpvar, size) | 583 scope.addLocal(tmpvar, size) |
502 prog.lastDst = rawParams[1] | 584 prog.lastDst = rawParams[1] |
585 if len(params) > 2: | |
586 size = params[2] | |
587 if size == 0: | |
588 size = 8 | |
589 elif size == 1: | |
590 size = 16 | |
591 else: | |
592 size = 32 | |
593 prog.lastSize = size | |
594 else: | |
595 prog.lastSize = None | |
503 return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1]) | 596 return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1]) |
504 | 597 |
505 def _asrCImpl(prog, params, rawParams, flagUpdates): | 598 def _asrCImpl(prog, params, rawParams, flagUpdates): |
506 needsCarry = False | 599 needsCarry = False |
507 if flagUpdates: | 600 if flagUpdates: |
521 return decl + '\n\t{dst} = ({a} >> {b}) | ({a} & {mask} ? 0xFFFFFFFFU << ({size} - {b}) : 0);'.format( | 614 return decl + '\n\t{dst} = ({a} >> {b}) | ({a} & {mask} ? 0xFFFFFFFFU << ({size} - {b}) : 0);'.format( |
522 a = params[0], b = params[1], dst = dst, mask = mask, size=size) | 615 a = params[0], b = params[1], dst = dst, mask = mask, size=size) |
523 | 616 |
524 def _sext(size, src): | 617 def _sext(size, src): |
525 if size == 16: | 618 if size == 16: |
526 return src | 0xFF00 if src & 0x80 else src | 619 return src | 0xFF00 if src & 0x80 else src & 0x7F |
527 else: | 620 else: |
528 return src | 0xFFFF0000 if src & 0x8000 else src | 621 return src | 0xFFFF0000 if src & 0x8000 else src & 0x7FFF |
529 | 622 |
530 def _sextCImpl(prog, params, rawParms): | 623 def _sextCImpl(prog, params, rawParms): |
531 if params[0] == 16: | 624 if params[0] == 16: |
532 fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src};' | 625 fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src} & 0x7F;' |
533 else: | 626 else: |
534 fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src};' | 627 fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src} & 0x7FFF;' |
535 return fmt.format(src=params[1], dst=params[2]) | 628 return fmt.format(src=params[1], dst=params[2]) |
536 | 629 |
537 def _getCarryCheck(prog): | 630 def _getCarryCheck(prog): |
538 carryFlag = None | 631 carryFlag = None |
539 for flag in prog.flags.flagCalc: | 632 for flag in prog.flags.flagOrder: |
540 if prog.flags.flagCalc[flag] == 'carry': | 633 if prog.flags.flagCalc[flag] == 'carry': |
541 carryFlag = flag | 634 carryFlag = flag |
635 break | |
542 if carryFlag is None: | 636 if carryFlag is None: |
543 raise Exception('adc requires a defined carry flag') | 637 raise Exception('adc requires a defined carry flag') |
544 carryStorage = prog.flags.getStorage(carryFlag) | 638 carryStorage = prog.flags.getStorage(carryFlag) |
545 if type(carryStorage) is tuple: | 639 if type(carryStorage) is tuple: |
546 reg,bit = carryStorage | 640 reg,bit = carryStorage |
548 return '({reg} & 1 << {bit})'.format(reg=reg, bit=bit) | 642 return '({reg} & 1 << {bit})'.format(reg=reg, bit=bit) |
549 else: | 643 else: |
550 return prog.resolveReg(carryStorage, None, (), False) | 644 return prog.resolveReg(carryStorage, None, (), False) |
551 | 645 |
552 def _adcCImpl(prog, params, rawParams, flagUpdates): | 646 def _adcCImpl(prog, params, rawParams, flagUpdates): |
647 needsSizeAdjust = False | |
648 if len(params) > 3: | |
649 size = params[3] | |
650 if size == 0: | |
651 size = 8 | |
652 elif size == 1: | |
653 size = 16 | |
654 else: | |
655 size = 32 | |
656 prog.lastSize = size | |
657 destSize = prog.paramSize(rawParams[2]) | |
658 if destSize > size: | |
659 needsSizeAdjust = True | |
660 prog.sizeAdjust = size | |
553 needsCarry = needsOflow = needsHalf = False | 661 needsCarry = needsOflow = needsHalf = False |
554 if flagUpdates: | 662 if flagUpdates: |
555 for flag in flagUpdates: | 663 for flag in flagUpdates: |
556 calc = prog.flags.flagCalc[flag] | 664 calc = prog.flags.flagCalc[flag] |
557 if calc == 'carry': | 665 if calc == 'carry': |
560 needsHalf = True | 668 needsHalf = True |
561 elif calc == 'overflow': | 669 elif calc == 'overflow': |
562 needsOflow = True | 670 needsOflow = True |
563 decl = '' | 671 decl = '' |
564 carryCheck = _getCarryCheck(prog) | 672 carryCheck = _getCarryCheck(prog) |
565 if needsCarry or needsOflow or needsHalf: | 673 vals = '1 : 0' |
566 size = prog.paramSize(rawParams[2]) | 674 if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust): |
675 if len(params) <= 3: | |
676 size = prog.paramSize(rawParams[2]) | |
567 if needsCarry: | 677 if needsCarry: |
568 size *= 2 | 678 size *= 2 |
569 decl,name = prog.getTemp(size) | 679 decl,name = prog.getTemp(size) |
570 dst = prog.carryFlowDst = name | 680 dst = prog.carryFlowDst = name |
571 prog.lastA = params[0] | 681 prog.lastA = params[0] |
572 prog.lastB = params[1] | 682 prog.lastB = params[1] |
573 prog.lastBFlow = '(~{b})'.format(b=params[1]) | 683 prog.lastBFlow = '(~{b})'.format(b=params[1]) |
684 if size == 64: | |
685 params[0] = '((uint64_t){a})'.format(a=params[0]) | |
686 params[1] = '((uint64_t){b})'.format(b=params[1]) | |
687 vals = '((uint64_t)1) : ((uint64_t)0)' | |
688 elif needsSizeAdjust: | |
689 decl,name = prog.getTemp(size) | |
690 dst = params[2] | |
691 return '{decl}\n\t{tmp} = ({a} & {mask}) + ({b} & {mask}) + ({check} ? 1 : 0);\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format( | |
692 decl = decl, tmp = name, a = a, b = b, op = op, dst = dst, mask = ((1 << size) - 1), check = carryCheck | |
693 ) | |
574 else: | 694 else: |
575 dst = params[2] | 695 dst = params[2] |
576 return decl + '\n\t{dst} = {a} + {b} + ({check} ? 1 : 0);'.format(dst = dst, | 696 return decl + '\n\t{dst} = {a} + {b} + ({check} ? {vals});'.format(dst = dst, |
577 a = params[0], b = params[1], check = carryCheck | 697 a = params[0], b = params[1], check = carryCheck, vals = vals |
578 ) | 698 ) |
579 | 699 |
580 def _sbcCImpl(prog, params, rawParams, flagUpdates): | 700 def _sbcCImpl(prog, params, rawParams, flagUpdates): |
701 needsSizeAdjust = False | |
702 if len(params) > 3: | |
703 size = params[3] | |
704 if size == 0: | |
705 size = 8 | |
706 elif size == 1: | |
707 size = 16 | |
708 else: | |
709 size = 32 | |
710 prog.lastSize = size | |
711 destSize = prog.paramSize(rawParams[2]) | |
712 if destSize > size: | |
713 needsSizeAdjust = True | |
714 prog.sizeAdjust = size | |
581 needsCarry = needsOflow = needsHalf = False | 715 needsCarry = needsOflow = needsHalf = False |
582 if flagUpdates: | 716 if flagUpdates: |
583 for flag in flagUpdates: | 717 for flag in flagUpdates: |
584 calc = prog.flags.flagCalc[flag] | 718 calc = prog.flags.flagCalc[flag] |
585 if calc == 'carry': | 719 if calc == 'carry': |
588 needsHalf = True | 722 needsHalf = True |
589 elif calc == 'overflow': | 723 elif calc == 'overflow': |
590 needsOflow = True | 724 needsOflow = True |
591 decl = '' | 725 decl = '' |
592 carryCheck = _getCarryCheck(prog) | 726 carryCheck = _getCarryCheck(prog) |
593 if needsCarry or needsOflow or needsHalf: | 727 vals = '1 : 0' |
728 if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust): | |
594 size = prog.paramSize(rawParams[2]) | 729 size = prog.paramSize(rawParams[2]) |
595 if needsCarry: | 730 if needsCarry: |
596 size *= 2 | 731 size *= 2 |
597 decl,name = prog.getTemp(size) | 732 decl,name = prog.getTemp(size) |
598 dst = prog.carryFlowDst = name | 733 dst = prog.carryFlowDst = name |
599 prog.lastA = params[1] | 734 prog.lastA = params[1] |
600 prog.lastB = params[0] | 735 prog.lastB = params[0] |
601 prog.lastBFlow = params[0] | 736 prog.lastBFlow = params[0] |
737 if size == 64: | |
738 params[1] = '((uint64_t){a})'.format(a=params[1]) | |
739 params[0] = '((uint64_t){b})'.format(b=params[0]) | |
740 vals = '((uint64_t)1) : ((uint64_t)0)' | |
741 elif needsSizeAdjust: | |
742 decl,name = prog.getTemp(size) | |
743 dst = params[2] | |
744 return '{decl}\n\t{tmp} = ({b} & {mask}) - ({a} & {mask}) - ({check} ? 1 : 0);\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format( | |
745 decl = decl, tmp = name, a = params[0], b = params[1], op = op, dst = dst, mask = ((1 << size) - 1), check = carryCheck | |
746 ) | |
602 else: | 747 else: |
603 dst = params[2] | 748 dst = params[2] |
604 return decl + '\n\t{dst} = {b} - {a} - ({check} ? 1 : 0);'.format(dst = dst, | 749 return decl + '\n\t{dst} = {b} - {a} - ({check} ? {vals});'.format(dst = dst, |
605 a = params[0], b = params[1], check=_getCarryCheck(prog) | 750 a = params[0], b = params[1], check=_getCarryCheck(prog), vals = vals |
606 ) | 751 ) |
607 | 752 |
608 def _rolCImpl(prog, params, rawParams, flagUpdates): | 753 def _rolCImpl(prog, params, rawParams, flagUpdates): |
609 needsCarry = False | 754 needsCarry = False |
610 if flagUpdates: | 755 if flagUpdates: |
695 'cmp': Op().addImplementation('c', None, _cmpCImpl), | 840 'cmp': Op().addImplementation('c', None, _cmpCImpl), |
696 'sext': Op(_sext).addImplementation('c', 2, _sextCImpl), | 841 'sext': Op(_sext).addImplementation('c', 2, _sextCImpl), |
697 'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format( | 842 'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format( |
698 pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]]) | 843 pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]]) |
699 )), | 844 )), |
845 'pcall': Op().addImplementation('c', None, lambda prog, params: '\n\t(({typ}){fun})({args});'.format( | |
846 typ = params[1], fun = params[0], args = ', '.join([str(p) for p in params[2:]]) | |
847 )), | |
700 'cycles': Op().addImplementation('c', None, | 848 'cycles': Op().addImplementation('c', None, |
701 lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format( | 849 lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format( |
702 params[0] | 850 params[0] |
703 ) | 851 ) |
704 ), | 852 ), |
705 'addsize': Op( | 853 'addsize': Op( |
706 lambda a, b: b + (2 * a if a else 1) | 854 lambda a, b: b + (2 * a if a else 1) |
707 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + {sz} ? {sz} * 2 : 1;'.format( | 855 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + ({sz} ? {sz} * 2 : 1);'.format( |
708 dst = params[2], sz = params[0], val = params[1] | 856 dst = params[2], sz = params[0], val = params[1] |
709 )), | 857 )), |
710 'decsize': Op( | 858 'decsize': Op( |
711 lambda a, b: b - (2 * a if a else 1) | 859 lambda a, b: b - (2 * a if a else 1) |
712 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - {sz} ? {sz} * 2 : 1;'.format( | 860 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - ({sz} ? {sz} * 2 : 1);'.format( |
713 dst = params[2], sz = params[0], val = params[1] | 861 dst = params[2], sz = params[0], val = params[1] |
714 )), | 862 )), |
715 'xchg': Op().addImplementation('c', (0,1), _xchgCImpl), | 863 'xchg': Op().addImplementation('c', (0,1), _xchgCImpl), |
716 'dispatch': Op().addImplementation('c', None, _dispatchCImpl), | 864 'dispatch': Op().addImplementation('c', None, _dispatchCImpl), |
717 'update_flags': Op().addImplementation('c', None, _updateFlagsCImpl), | 865 'update_flags': Op().addImplementation('c', None, _updateFlagsCImpl), |
727 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates): | 875 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates): |
728 procParams = [] | 876 procParams = [] |
729 allParamsConst = flagUpdates is None and not prog.conditional | 877 allParamsConst = flagUpdates is None and not prog.conditional |
730 opDef = _opMap.get(self.op) | 878 opDef = _opMap.get(self.op) |
731 for param in self.params: | 879 for param in self.params: |
732 allowConst = (self.op in prog.subroutines or len(procParams) != len(self.params) - 1) and param in parent.regValues | |
733 isDst = (not opDef is None) and len(procParams) in opDef.outOp | 880 isDst = (not opDef is None) and len(procParams) in opDef.outOp |
881 allowConst = (self.op in prog.subroutines or not isDst) and param in parent.regValues | |
734 if isDst and self.op == 'xchg': | 882 if isDst and self.op == 'xchg': |
735 #xchg uses its regs as both source and destination | 883 #xchg uses its regs as both source and destination |
736 #we need to resolve as both so that disperse/coalesce flag stuff gets done | 884 #we need to resolve as both so that disperse/coalesce flag stuff gets done |
737 prog.resolveParam(param, parent, fieldVals, allowConst, False) | 885 prog.resolveParam(param, parent, fieldVals, allowConst, False) |
738 param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst) | 886 param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst) |
792 if end in fieldVals: | 940 if end in fieldVals: |
793 param = begin + '.' + str(fieldVals[end]) | 941 param = begin + '.' + str(fieldVals[end]) |
794 else: | 942 else: |
795 if param in fieldVals: | 943 if param in fieldVals: |
796 param = fieldVals[param] | 944 param = fieldVals[param] |
945 else: | |
946 maybeLocal = parent.resolveLocal(param) | |
947 if maybeLocal and maybeLocal in parent.regValues: | |
948 param = parent.regValues[maybeLocal] | |
797 procParams.append(param) | 949 procParams.append(param) |
798 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent) | 950 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent) |
799 else: | 951 else: |
800 output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');') | 952 output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');') |
801 prog.lastOp = self | 953 prog.lastOp = self |
870 oldCond = prog.conditional | 1022 oldCond = prog.conditional |
871 prog.conditional = True | 1023 prog.conditional = True |
872 output.append('\n\tswitch(' + param + ')') | 1024 output.append('\n\tswitch(' + param + ')') |
873 output.append('\n\t{') | 1025 output.append('\n\t{') |
874 for case in self.cases: | 1026 for case in self.cases: |
875 temp = prog.temp.copy() | 1027 #temp = prog.temp.copy() |
876 self.current_locals = self.case_locals[case] | 1028 self.current_locals = self.case_locals[case] |
877 self.regValues = dict(self.parent.regValues) | 1029 self.regValues = dict(self.parent.regValues) |
878 output.append('\n\tcase {0}U: '.format(case) + '{') | 1030 output.append('\n\tcase {0}U: '.format(case) + '{') |
879 for local in self.case_locals[case]: | 1031 for local in self.case_locals[case]: |
880 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[case][local], local)) | 1032 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[case][local], local)) |
881 self.processOps(prog, fieldVals, output, otype, self.cases[case]) | 1033 self.processOps(prog, fieldVals, output, otype, self.cases[case]) |
882 output.append('\n\tbreak;') | 1034 output.append('\n\tbreak;') |
883 output.append('\n\t}') | 1035 output.append('\n\t}') |
884 prog.temp = temp | 1036 #prog.temp = temp |
885 if self.default: | 1037 if self.default: |
886 temp = prog.temp.copy() | 1038 #temp = prog.temp.copy() |
887 self.current_locals = self.default_locals | 1039 self.current_locals = self.default_locals |
888 self.regValues = dict(self.parent.regValues) | 1040 self.regValues = dict(self.parent.regValues) |
889 output.append('\n\tdefault: {') | 1041 output.append('\n\tdefault: {') |
890 for local in self.default_locals: | 1042 for local in self.default_locals: |
891 output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local)) | 1043 output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local)) |
892 self.processOps(prog, fieldVals, output, otype, self.default) | 1044 self.processOps(prog, fieldVals, output, otype, self.default) |
893 prog.temp = temp | 1045 #prog.temp = temp |
894 output.append('\n\t}') | 1046 output.append('\n\t}') |
895 prog.conditional = oldCond | 1047 prog.conditional = oldCond |
896 prog.popScope() | 1048 prog.popScope() |
897 | 1049 |
898 def __str__(self): | 1050 def __str__(self): |
913 return '\n\tif ({a} >= {b}) '.format(a=params[1], b = params[0]) + '{' | 1065 return '\n\tif ({a} >= {b}) '.format(a=params[1], b = params[0]) + '{' |
914 else: | 1066 else: |
915 raise Exception(">=U not implemented in the general case yet") | 1067 raise Exception(">=U not implemented in the general case yet") |
916 | 1068 |
917 def _eqCImpl(prog, parent, fieldVals, output): | 1069 def _eqCImpl(prog, parent, fieldVals, output): |
918 return '\n\tif (!{a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {})) | 1070 if prog.lastOp.op == 'cmp': |
1071 output.pop() | |
1072 params = [prog.resolveParam(p, parent, fieldVals) for p in prog.lastOp.params] | |
1073 return '\n\tif ({a} == {b}) '.format(a=params[1], b = params[0]) + '{' | |
1074 else: | |
1075 return '\n\tif (!{a}) {{'.format(a=prog.resolveParam(prog.lastDst, None, {})) | |
919 | 1076 |
920 def _neqCImpl(prog, parent, fieldVals, output): | 1077 def _neqCImpl(prog, parent, fieldVals, output): |
921 return '\n\tif ({a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {})) | 1078 return '\n\tif ({a}) {{'.format(a=prog.resolveParam(prog.lastDst, None, {})) |
922 | 1079 |
923 _ifCmpImpl = { | 1080 _ifCmpImpl = { |
924 'c': { | 1081 'c': { |
925 '>=U': _geuCImpl, | 1082 '>=U': _geuCImpl, |
926 '=': _eqCImpl, | 1083 '=': _eqCImpl, |
984 else: | 1141 else: |
985 self._genFalseBody(prog, fieldVals, output, otype) | 1142 self._genFalseBody(prog, fieldVals, output, otype) |
986 | 1143 |
987 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates): | 1144 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates): |
988 self.regValues = parent.regValues | 1145 self.regValues = parent.regValues |
989 try: | 1146 if self.cond in prog.booleans: |
990 self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype) | 1147 self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype) |
991 except Exception: | 1148 else: |
992 if self.cond in _ifCmpImpl[otype]: | 1149 if self.cond in _ifCmpImpl[otype]: |
993 oldCond = prog.conditional | 1150 oldCond = prog.conditional |
994 prog.conditional = True | 1151 prog.conditional = True |
995 temp = prog.temp.copy() | 1152 #temp = prog.temp.copy() |
996 output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output)) | 1153 output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output)) |
997 self._genTrueBody(prog, fieldVals, output, otype) | 1154 self._genTrueBody(prog, fieldVals, output, otype) |
998 prog.temp = temp | 1155 #prog.temp = temp |
999 if self.elseBody: | 1156 if self.elseBody: |
1000 temp = prog.temp.copy() | 1157 #temp = prog.temp.copy() |
1001 output.append('\n\t} else {') | 1158 output.append('\n\t} else {') |
1002 self._genFalseBody(prog, fieldVals, output, otype) | 1159 self._genFalseBody(prog, fieldVals, output, otype) |
1003 prog.temp = temp | 1160 #prog.temp = temp |
1004 output.append('\n\t}') | 1161 output.append('\n\t}') |
1005 prog.conditional = oldCond | 1162 prog.conditional = oldCond |
1006 else: | 1163 else: |
1007 cond = prog.resolveParam(self.cond, parent, fieldVals) | 1164 cond = prog.resolveParam(self.cond, parent, fieldVals) |
1008 if type(cond) is int: | 1165 if type(cond) is int: |
1009 self._genConstParam(cond, prog, fieldVals, output, otype) | 1166 self._genConstParam(cond, prog, fieldVals, output, otype) |
1010 else: | 1167 else: |
1011 temp = prog.temp.copy() | 1168 #temp = prog.temp.copy() |
1012 output.append('\n\tif ({cond}) '.format(cond=cond) + '{') | 1169 output.append('\n\tif ({cond}) '.format(cond=cond) + '{') |
1013 oldCond = prog.conditional | 1170 oldCond = prog.conditional |
1014 prog.conditional = True | 1171 prog.conditional = True |
1015 self._genTrueBody(prog, fieldVals, output, otype) | 1172 self._genTrueBody(prog, fieldVals, output, otype) |
1016 prog.temp = temp | 1173 #prog.temp = temp |
1017 if self.elseBody: | 1174 if self.elseBody: |
1018 temp = prog.temp.copy() | 1175 #temp = prog.temp.copy() |
1019 output.append('\n\t} else {') | 1176 output.append('\n\t} else {') |
1020 self._genFalseBody(prog, fieldVals, output, otype) | 1177 self._genFalseBody(prog, fieldVals, output, otype) |
1021 prog.temp = temp | 1178 #prog.temp = temp |
1022 output.append('\n\t}') | 1179 output.append('\n\t}') |
1023 prog.conditional = oldCond | 1180 prog.conditional = oldCond |
1024 | 1181 |
1025 | 1182 |
1026 def __str__(self): | 1183 def __str__(self): |
1127 class Flags: | 1284 class Flags: |
1128 def __init__(self): | 1285 def __init__(self): |
1129 self.flagBits = {} | 1286 self.flagBits = {} |
1130 self.flagCalc = {} | 1287 self.flagCalc = {} |
1131 self.flagStorage = {} | 1288 self.flagStorage = {} |
1289 self.flagOrder = [] | |
1132 self.flagReg = None | 1290 self.flagReg = None |
1133 self.storageToFlags = {} | 1291 self.storageToFlags = {} |
1134 self.maxBit = -1 | 1292 self.maxBit = -1 |
1135 | 1293 |
1136 def processLine(self, parts): | 1294 def processLine(self, parts): |
1151 self.flagBits[flag] = bit | 1309 self.flagBits[flag] = bit |
1152 self.flagCalc[flag] = calc | 1310 self.flagCalc[flag] = calc |
1153 self.flagStorage[flag] = storage | 1311 self.flagStorage[flag] = storage |
1154 storage,_,storebit = storage.partition('.') | 1312 storage,_,storebit = storage.partition('.') |
1155 self.storageToFlags.setdefault(storage, []).append((storebit, flag)) | 1313 self.storageToFlags.setdefault(storage, []).append((storebit, flag)) |
1314 self.flagOrder.append(flag) | |
1156 return self | 1315 return self |
1157 | 1316 |
1158 def getStorage(self, flag): | 1317 def getStorage(self, flag): |
1159 if not flag in self.flagStorage: | 1318 if not flag in self.flagStorage: |
1160 raise Exception('Undefined flag ' + flag) | 1319 raise Exception('Undefined flag ' + flag) |
1310 self.lastOp = None | 1469 self.lastOp = None |
1311 self.carryFlowDst = None | 1470 self.carryFlowDst = None |
1312 self.lastA = None | 1471 self.lastA = None |
1313 self.lastB = None | 1472 self.lastB = None |
1314 self.lastBFlow = None | 1473 self.lastBFlow = None |
1474 self.sizeAdjust = None | |
1315 self.conditional = False | 1475 self.conditional = False |
1316 self.declares = [] | 1476 self.declares = [] |
1477 self.lastSize = None | |
1317 | 1478 |
1318 def __str__(self): | 1479 def __str__(self): |
1319 pieces = [] | 1480 pieces = [] |
1320 for reg in self.regs: | 1481 for reg in self.regs: |
1321 pieces.append(str(self.regs[reg])) | 1482 pieces.append(str(self.regs[reg])) |
1409 body = [] | 1570 body = [] |
1410 pieces = [] | 1571 pieces = [] |
1411 for include in self.includes: | 1572 for include in self.includes: |
1412 body.append('#include "{0}"\n'.format(include)) | 1573 body.append('#include "{0}"\n'.format(include)) |
1413 if self.dispatch == 'call': | 1574 if self.dispatch == 'call': |
1414 body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix)) | 1575 body.append('\nstatic void unimplemented({pre}context *context, uint32_t target_cycle)'.format(pre = self.prefix)) |
1415 body.append('\n{') | 1576 body.append('\n{') |
1416 body.append('\n\tfatal_error("Unimplemented instruction\\n");') | 1577 body.append('\n\tfatal_error("Unimplemented instruction\\n");') |
1417 body.append('\n}\n') | 1578 body.append('\n}\n') |
1418 body.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix)) | 1579 body.append('\ntypedef void (*impl_fun)({pre}context *context, uint32_t target_cycle);'.format(pre=self.prefix)) |
1419 for table in self.extra_tables: | 1580 for table in self.extra_tables: |
1420 body.append('\nstatic impl_fun impl_{name}[{sz}];'.format(name = table, sz=(1 << self.opsize))) | 1581 body.append('\nstatic impl_fun impl_{name}[{sz}];'.format(name = table, sz=(1 << self.opsize))) |
1421 body.append('\nstatic impl_fun impl_main[{sz}];'.format(sz=(1 << self.opsize))) | 1582 body.append('\nstatic impl_fun impl_main[{sz}];'.format(sz=(1 << self.opsize))) |
1422 elif self.dispatch == 'goto': | 1583 elif self.dispatch == 'goto': |
1423 body.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type)) | 1584 body.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type)) |
1453 | 1614 |
1454 def getTemp(self, size): | 1615 def getTemp(self, size): |
1455 if size in self.temp: | 1616 if size in self.temp: |
1456 return ('', self.temp[size]) | 1617 return ('', self.temp[size]) |
1457 self.temp[size] = 'gen_tmp{sz}__'.format(sz=size); | 1618 self.temp[size] = 'gen_tmp{sz}__'.format(sz=size); |
1458 return ('\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size), self.temp[size]) | 1619 return ('', self.temp[size]) |
1459 | 1620 |
1460 def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False): | 1621 def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False): |
1461 keepGoing = True | 1622 keepGoing = True |
1462 while keepGoing: | 1623 while keepGoing: |
1463 keepGoing = False | 1624 keepGoing = False |
1475 return parent.regValues[param] | 1636 return parent.regValues[param] |
1476 maybeLocal = parent.resolveLocal(param) | 1637 maybeLocal = parent.resolveLocal(param) |
1477 if maybeLocal: | 1638 if maybeLocal: |
1478 if isdst: | 1639 if isdst: |
1479 self.lastDst = param | 1640 self.lastDst = param |
1641 self.lastSize = None | |
1480 return maybeLocal | 1642 return maybeLocal |
1481 if param in fieldVals: | 1643 if param in fieldVals: |
1482 param = fieldVals[param] | 1644 param = fieldVals[param] |
1483 fieldVals = {} | 1645 fieldVals = {} |
1484 keepGoing = True | 1646 keepGoing = True |
1485 elif param in self.meta: | 1647 elif param in self.meta: |
1486 param = self.meta[param] | 1648 param = self.meta[param] |
1487 keepGoing = True | 1649 keepGoing = True |
1488 elif self.isReg(param): | 1650 elif self.isReg(param): |
1489 return self.resolveReg(param, parent, fieldVals, isdst) | 1651 return self.resolveReg(param, parent, fieldVals, isdst) |
1652 elif param in self.regs.pointers: | |
1653 return 'context->' + param | |
1490 if isdst: | 1654 if isdst: |
1491 self.lastDst = param | 1655 self.lastDst = param |
1656 self.lastSize = None | |
1492 return param | 1657 return param |
1493 | 1658 |
1494 def isReg(self, name): | 1659 def isReg(self, name): |
1495 if not type(name) is str: | 1660 if not type(name) is str: |
1496 return False | 1661 return False |
1548 if sep and self.regs.isRegArray(begin): | 1713 if sep and self.regs.isRegArray(begin): |
1549 return self.regs.regArrays[begin][0] | 1714 return self.regs.regArrays[begin][0] |
1550 if self.regs.isReg(name): | 1715 if self.regs.isReg(name): |
1551 return self.regs.regs[name] | 1716 return self.regs.regs[name] |
1552 return 32 | 1717 return 32 |
1718 | |
1719 def getLastSize(self): | |
1720 if self.lastSize: | |
1721 return self.lastSize | |
1722 return self.paramSize(self.lastDst) | |
1553 | 1723 |
1554 def pushScope(self, scope): | 1724 def pushScope(self, scope): |
1555 self.scopes.append(scope) | 1725 self.scopes.append(scope) |
1556 self.currentScope = scope | 1726 self.currentScope = scope |
1557 | 1727 |