comparison cpu_dsl.py @ 1769:8fe162bdb038 mame_interp

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Fri, 01 Mar 2019 14:17:29 -0800
parents 7b6831305a6a
children 0c1491818f4b
comparison
equal deleted inserted replaced
1768:63256371046f 1769:8fe162bdb038
17 elif parts[0] == 'end': 17 elif parts[0] == 'end':
18 raise Exception('end is only allowed inside a switch or if block') 18 raise Exception('end is only allowed inside a switch or if block')
19 else: 19 else:
20 self.addOp(NormalOp(parts)) 20 self.addOp(NormalOp(parts))
21 return self 21 return self
22
23 def processOps(self, prog, fieldVals, output, otype, oplist):
24 for i in range(0, len(oplist)):
25 if i + 1 < len(oplist) and oplist[i+1].op == 'update_flags':
26 flagUpdates, _ = prog.flags.parseFlagUpdate(oplist[i+1].params[0])
27 else:
28 flagUpdates = None
29 oplist[i].generate(prog, self, fieldVals, output, otype, flagUpdates)
22 30
23 def resolveLocal(self, name): 31 def resolveLocal(self, name):
24 return None 32 return None
25 33
26 class ChildBlock(Block): 34 class ChildBlock(Block):
45 self.varyingBits += fields[field][1] 53 self.varyingBits += fields[field][1]
46 54
47 def addOp(self, op): 55 def addOp(self, op):
48 if op.op == 'local': 56 if op.op == 'local':
49 name = op.params[0] 57 name = op.params[0]
50 size = op.params[1] 58 size = int(op.params[1])
51 self.locals[name] = size 59 self.locals[name] = size
52 elif op.op == 'invalid': 60 elif op.op == 'invalid':
53 name = op.params[0] 61 name = op.params[0]
54 value = int(op.params[1]) 62 value = int(op.params[1])
55 self.invalidFieldValues.setdefault(name, set()).add(value) 63 self.invalidFieldValues.setdefault(name, set()).add(value)
119 self.regValues = {} 127 self.regValues = {}
120 for var in self.locals: 128 for var in self.locals:
121 output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)) 129 output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var))
122 self.newLocals = [] 130 self.newLocals = []
123 fieldVals,_ = self.getFieldVals(value) 131 fieldVals,_ = self.getFieldVals(value)
124 for op in self.implementation: 132 self.processOps(prog, fieldVals, output, otype, self.implementation)
125 op.generate(prog, self, fieldVals, output, otype) 133
126 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{' 134 if prog.dispatch == 'call':
135 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{'
136 elif prog.dispatch == 'goto':
137 begin = '\n' + self.generateName(value) + ': {'
138 else:
139 raise Exception('Unsupported dispatch type ' + prog.dispatch)
127 if prog.needFlagCoalesce: 140 if prog.needFlagCoalesce:
128 begin += prog.flags.coalesceFlags(prog, otype) 141 begin += prog.flags.coalesceFlags(prog, otype)
129 if prog.needFlagDisperse: 142 if prog.needFlagDisperse:
130 output.append(prog.flags.disperseFlags(prog, otype)) 143 output.append(prog.flags.disperseFlags(prog, otype))
131 for var in self.newLocals: 144 for var in self.newLocals:
132 begin += '\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var) 145 begin += '\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)
133 prog.popScope() 146 prog.popScope()
147 if prog.dispatch == 'goto':
148 output += prog.nextInstruction(otype)
134 return begin + ''.join(output) + '\n}' 149 return begin + ''.join(output) + '\n}'
135 150
136 def __str__(self): 151 def __str__(self):
137 pieces = [self.name + ' ' + hex(self.value) + ' ' + str(self.fields)] 152 pieces = [self.name + ' ' + hex(self.value) + ' ' + str(self.fields)]
138 for name in self.locals: 153 for name in self.locals:
148 self.implementation = [] 163 self.implementation = []
149 self.args = [] 164 self.args = []
150 self.arg_map = {} 165 self.arg_map = {}
151 self.locals = {} 166 self.locals = {}
152 self.regValues = {} 167 self.regValues = {}
168 self.argValues = {}
153 169
154 def addOp(self, op): 170 def addOp(self, op):
155 if op.op == 'arg': 171 if op.op == 'arg':
156 name = op.params[0] 172 name = op.params[0]
157 size = op.params[1] 173 size = int(op.params[1])
158 self.arg_map[name] = len(self.args) 174 self.arg_map[name] = len(self.args)
159 self.args.append((name, size)) 175 self.args.append((name, size))
160 elif op.op == 'local': 176 elif op.op == 'local':
161 name = op.params[0] 177 name = op.params[0]
162 size = op.params[1] 178 size = int(op.params[1])
163 self.locals[name] = size 179 self.locals[name] = size
164 else: 180 else:
165 self.implementation.append(op) 181 self.implementation.append(op)
166 182
167 def resolveLocal(self, name): 183 def resolveLocal(self, name):
171 187
172 def addLocal(self, name, size): 188 def addLocal(self, name, size):
173 self.locals[name] = size 189 self.locals[name] = size
174 190
175 def localSize(self, name): 191 def localSize(self, name):
176 return self.locals.get(name) 192 if name in self.locals:
193 return self.locals[name]
194 if name in self.arg_map:
195 argIndex = self.arg_map[name]
196 return self.args[argIndex][1]
197 return None
177 198
178 def inline(self, prog, params, output, otype, parent): 199 def inline(self, prog, params, output, otype, parent):
179 if len(params) != len(self.args): 200 if len(params) != len(self.args):
180 raise Exception('{0} expects {1} arguments, but was called with {2}'.format(self.name, len(self.args), len(params))) 201 raise Exception('{0} expects {1} arguments, but was called with {2}'.format(self.name, len(self.args), len(params)))
181 argValues = {} 202 argValues = {}
187 argValues[name] = params[i] 208 argValues[name] = params[i]
188 i += 1 209 i += 1
189 for name in self.locals: 210 for name in self.locals:
190 size = self.locals[name] 211 size = self.locals[name]
191 output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name)) 212 output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name))
192 for op in self.implementation: 213 self.argValues = argValues
193 op.generate(prog, self, argValues, output, otype) 214 self.processOps(prog, argValues, output, otype, self.implementation)
194 prog.popScope() 215 prog.popScope()
195 216
196 def __str__(self): 217 def __str__(self):
197 pieces = [self.name] 218 pieces = [self.name]
198 for name,size in self.args: 219 for name,size in self.args:
207 def __init__(self, evalFun = None): 228 def __init__(self, evalFun = None):
208 self.evalFun = evalFun 229 self.evalFun = evalFun
209 self.impls = {} 230 self.impls = {}
210 self.outOp = () 231 self.outOp = ()
211 def cBinaryOperator(self, op): 232 def cBinaryOperator(self, op):
212 def _impl(prog, params): 233 def _impl(prog, params, rawParams, flagUpdates):
213 if op == '-': 234 if op == '-':
214 a = params[1] 235 a = params[1]
215 b = params[0] 236 b = params[0]
216 else: 237 else:
217 a = params[0] 238 a = params[0]
218 b = params[1] 239 b = params[1]
219 return '\n\t{dst} = {a} {op} {b};'.format( 240 needsCarry = needsOflow = needsHalf = False
220 dst = params[2], a = a, b = b, op = op 241 if flagUpdates:
242 for flag in flagUpdates:
243 calc = prog.flags.flagCalc[flag]
244 if calc == 'carry':
245 needsCarry = True
246 elif calc == 'half-carry':
247 needsHalf = True
248 elif calc == 'overflow':
249 needsOflow = True
250 decl = ''
251 if needsCarry or needsOflow or needsHalf:
252 size = prog.paramSize(rawParams[2])
253 if needsCarry and op != 'lsr':
254 size *= 2
255 decl,name = prog.getTemp(size)
256 dst = prog.carryFlowDst = name
257 prog.lastA = a
258 prog.lastB = b
259 prog.lastBFlow = b if op == '-' else '(~{b})'.format(b=b)
260 else:
261 dst = params[2]
262 return decl + '\n\t{dst} = {a} {op} {b};'.format(
263 dst = dst, a = a, b = b, op = op
221 ) 264 )
222 self.impls['c'] = _impl 265 self.impls['c'] = _impl
223 self.outOp = (2,) 266 self.outOp = (2,)
224 return self 267 return self
225 def cUnaryOperator(self, op): 268 def cUnaryOperator(self, op):
226 def _impl(prog, params): 269 def _impl(prog, params, rawParams, flagUpdates):
227 return '\n\t{dst} = {op}{a};'.format( 270 dst = params[1]
228 dst = params[1], a = params[0], op = op 271 decl = ''
272 if op == '-':
273 if flagUpdates:
274 for flag in flagUpdates:
275 calc = prog.flags.flagCalc[flag]
276 if calc == 'carry':
277 needsCarry = True
278 elif calc == 'half-carry':
279 needsHalf = True
280 elif calc == 'overflow':
281 needsOflow = True
282 if needsCarry or needsOflow or needsHalf:
283 size = prog.paramSize(rawParams[1])
284 if needsCarry:
285 size *= 2
286 decl,name = prog.getTemp(size)
287 dst = prog.carryFlowDst = name
288 prog.lastA = 0
289 prog.lastB = params[0]
290 prog.lastBFlow = params[0]
291 return decl + '\n\t{dst} = {op}{a};'.format(
292 dst = dst, a = params[0], op = op
229 ) 293 )
230 self.impls['c'] = _impl 294 self.impls['c'] = _impl
231 self.outOp = (1,) 295 self.outOp = (1,)
232 return self 296 return self
233 def addImplementation(self, lang, outOp, impl): 297 def addImplementation(self, lang, outOp, impl):
242 return self.evalFun(*params) 306 return self.evalFun(*params)
243 def canEval(self): 307 def canEval(self):
244 return not self.evalFun is None 308 return not self.evalFun is None
245 def numArgs(self): 309 def numArgs(self):
246 return self.evalFun.__code__.co_argcount 310 return self.evalFun.__code__.co_argcount
247 def generate(self, otype, prog, params, rawParams): 311 def numParams(self):
312 if self.outOp:
313 params = max(self.outOp) + 1
314 else:
315 params = 0
316 if self.evalFun:
317 params = max(params, self.numArgs())
318 return params
319 def generate(self, otype, prog, params, rawParams, flagUpdates):
248 if self.impls[otype].__code__.co_argcount == 2: 320 if self.impls[otype].__code__.co_argcount == 2:
249 return self.impls[otype](prog, params) 321 return self.impls[otype](prog, params)
250 else: 322 elif self.impls[otype].__code__.co_argcount == 3:
251 return self.impls[otype](prog, params, rawParams) 323 return self.impls[otype](prog, params, rawParams)
324 else:
325 return self.impls[otype](prog, params, rawParams, flagUpdates)
252 326
253 327
254 def _xchgCImpl(prog, params, rawParams): 328 def _xchgCImpl(prog, params, rawParams):
255 size = prog.paramSize(rawParams[0]) 329 size = prog.paramSize(rawParams[0])
256 decl,name = prog.getTemp(size) 330 decl,name = prog.getTemp(size)
259 def _dispatchCImpl(prog, params): 333 def _dispatchCImpl(prog, params):
260 if len(params) == 1: 334 if len(params) == 1:
261 table = 'main' 335 table = 'main'
262 else: 336 else:
263 table = params[1] 337 table = params[1]
264 return '\n\timpl_{tbl}[{op}](context);'.format(tbl = table, op = params[0]) 338 if prog.dispatch == 'call':
339 return '\n\timpl_{tbl}[{op}](context);'.format(tbl = table, op = params[0])
340 elif prog.dispatch == 'goto':
341 return '\n\tgoto *impl_{tbl}[{op}];'.format(tbl = table, op = params[0])
342 else:
343 raise Exception('Unsupported dispatch type ' + prog.dispatch)
265 344
266 def _updateFlagsCImpl(prog, params, rawParams): 345 def _updateFlagsCImpl(prog, params, rawParams):
267 i = 0 346 autoUpdate, explicit = prog.flags.parseFlagUpdate(params[0])
268 last = ''
269 autoUpdate = set()
270 explicit = {}
271 for c in params[0]:
272 if c.isdigit():
273 if last.isalpha():
274 num = int(c)
275 if num > 1:
276 raise Exception(c + ' is not a valid digit for update_flags')
277 explicit[last] = num
278 last = c
279 else:
280 raise Exception('Digit must follow flag letter in update_flags')
281 else:
282 if last.isalpha():
283 autoUpdate.add(last)
284 last = c
285 if last.isalpha():
286 autoUpdate.add(last)
287 output = [] 347 output = []
288 #TODO: handle autoUpdate flags 348 parity = None
349 directFlags = {}
289 for flag in autoUpdate: 350 for flag in autoUpdate:
290 calc = prog.flags.flagCalc[flag] 351 calc = prog.flags.flagCalc[flag]
291 calc,_,resultBit = calc.partition('-') 352 calc,_,resultBit = calc.partition('-')
292 lastDst = prog.resolveParam(prog.lastDst, None, {}) 353 if prog.carryFlowDst:
354 lastDst = prog.carryFlowDst
355 else:
356 lastDst = prog.resolveParam(prog.lastDst, prog.currentScope, {})
293 storage = prog.flags.getStorage(flag) 357 storage = prog.flags.getStorage(flag)
294 if calc == 'bit' or calc == 'sign': 358 if calc == 'bit' or calc == 'sign' or calc == 'carry' or calc == 'half' or calc == 'overflow':
359 myRes = lastDst
295 if calc == 'sign': 360 if calc == 'sign':
296 resultBit = prog.paramSize(prog.lastDst) - 1 361 resultBit = prog.paramSize(prog.lastDst) - 1
297 else: 362 elif calc == 'carry':
298 resultBit = int(resultBit) 363 if prog.lastOp.op in ('asr', 'lsr'):
364 resultBit = 0
365 myRes = prog.lastA
366 else:
367 resultBit = prog.paramSize(prog.lastDst)
368 if prog.lastOp.op == 'ror':
369 resultBit -= 1
370 elif calc == 'half':
371 resultBit = prog.paramSize(prog.lastDst) - 4
372 myRes = '({a} ^ {b} ^ {res})'.format(a = prog.lastA, b = prog.lastB, res = lastDst)
373 elif calc == 'overflow':
374 resultBit = prog.paramSize(prog.lastDst) - 1
375 myRes = '((({a} ^ {b})) & ({a} ^ {res}))'.format(a = prog.lastA, b = prog.lastBFlow, res = lastDst)
376 else:
377 #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
379 resultBit = int(resultBit) + prog.paramSize(prog.lastDst) - 8
299 if type(storage) is tuple: 380 if type(storage) is tuple:
300 reg,storageBit = storage 381 reg,storageBit = storage
301 reg = prog.resolveParam(reg, None, {})
302 if storageBit == resultBit: 382 if storageBit == resultBit:
303 #TODO: optimize this case 383 directFlags.setdefault((reg, myRes), []).append(resultBit)
304 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format( 384 else:
305 reg = reg, mask = 1 << resultBit, res = lastDst 385 reg = prog.resolveParam(reg, None, {})
306 ))
307 else:
308 if resultBit > storageBit: 386 if resultBit > storageBit:
309 op = '>>' 387 op = '>>'
310 shift = resultBit - storageBit 388 shift = resultBit - storageBit
311 else: 389 else:
312 op = '<<' 390 op = '<<'
313 shift = storageBit - resultBit 391 shift = storageBit - resultBit
314 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} {op} {shift}U & {mask}U);'.format( 392 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} {op} {shift}U & {mask}U);'.format(
315 reg = reg, mask = 1 << storageBit, res = lastDst, op = op, shift = shift 393 reg = reg, mask = 1 << storageBit, res = myRes, op = op, shift = shift
316 )) 394 ))
317 else: 395 else:
318 reg = prog.resolveParam(storage, None, {}) 396 reg = prog.resolveParam(storage, None, {})
319 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=lastDst, mask = 1 << resultBit)) 397 maxBit = prog.paramSize(storage) - 1
398 if resultBit > maxBit:
399 output.append('\n\t{reg} = {res} >> {shift} & {mask}U;'.format(reg=reg, res=myRes, shift = resultBit - maxBit, mask = 1 << maxBit))
400 else:
401 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit))
320 elif calc == 'zero': 402 elif calc == 'zero':
403 if prog.carryFlowDst:
404 realSize = prog.paramSize(prog.lastDst)
405 if realSize != prog.paramSize(prog.carryFlowDst):
406 lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1)
321 if type(storage) is tuple: 407 if type(storage) is tuple:
322 reg,storageBit = storage 408 reg,storageBit = storage
323 reg = prog.resolveParam(reg, None, {}) 409 reg = prog.resolveParam(reg, None, {})
324 output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format( 410 output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format(
325 reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit 411 reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit
326 )) 412 ))
327 elif prog.paramSize(prog.lastDst) > prog.paramSize(storage): 413 else:
328 reg = prog.resolveParam(storage, None, {}) 414 reg = prog.resolveParam(storage, None, {})
329 output.append('\n\t{reg} = {res} != 0;'.format( 415 output.append('\n\t{reg} = {res} == 0;'.format(
330 reg = reg, res = lastDst 416 reg = reg, res = lastDst
331 )) 417 ))
332 else:
333 reg = prog.resolveParam(storage, None, {})
334 output.append('\n\t{reg} = {res};'.format(reg = reg, res = lastDst))
335 elif calc == 'half-carry':
336 pass
337 elif calc == 'carry':
338 pass
339 elif calc == 'overflow':
340 pass
341 elif calc == 'parity': 418 elif calc == 'parity':
342 pass 419 parity = storage
420 paritySize = prog.paramSize(prog.lastDst)
421 if prog.carryFlowDst:
422 parityDst = paritySrc = prog.carryFlowDst
423 else:
424 paritySrc = lastDst
425 decl,name = prog.getTemp(paritySize)
426 output.append(decl)
427 parityDst = name
428 else:
429 raise Exception('Unknown flag calc type: ' + calc)
430 for reg, myRes in directFlags:
431 bits = directFlags[(reg, myRes)]
432 resolved = prog.resolveParam(reg, None, {})
433 if len(bits) == len(prog.flags.storageToFlags[reg]):
434 output.append('\n\t{reg} = {res};'.format(reg = resolved, res = myRes))
435 else:
436 mask = 0
437 for bit in bits:
438 mask |= 1 << bit
439 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format(
440 reg = resolved, mask = mask, res = myRes
441 ))
442 if prog.carryFlowDst:
443 if prog.lastOp.op != 'cmp':
444 output.append('\n\t{dst} = {tmpdst};'.format(dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst))
445 prog.carryFlowDst = None
446 if parity:
447 if paritySize > 8:
448 if paritySize > 16:
449 output.append('\n\t{dst} = {src} ^ ({src} >> 16);'.format(dst=parityDst, src=paritySrc))
450 paritySrc = parityDst
451 output.append('\n\t{dst} = {src} ^ ({src} >> 8);'.format(dst=parityDst, src=paritySrc))
452 paritySrc = parityDst
453 output.append('\n\t{dst} = ({src} ^ ({src} >> 4)) & 0xF;'.format(dst=parityDst, src=paritySrc))
454 if type(parity) is tuple:
455 reg,bit = parity
456 reg = prog.resolveParam(reg, None, {})
457 output.append('\n\t{flag} = ({flag} & ~{mask}U) | ((0x6996 >> {parity}) << {bit} & {mask}U);'.format(
458 flag=reg, mask = 1 << bit, bit = bit, parity = parityDst
459 ))
460 else:
461 reg = prog.resolveParam(parity, None, {})
462 output.append('\n\t{flag} = 0x9669 >> {parity} & 1;'.format(flag=reg, parity=parityDst))
463
343 #TODO: combine explicit flags targeting the same storage location 464 #TODO: combine explicit flags targeting the same storage location
344 for flag in explicit: 465 for flag in explicit:
345 location = prog.flags.getStorage(flag) 466 location = prog.flags.getStorage(flag)
346 if type(location) is tuple: 467 if type(location) is tuple:
347 reg,bit = location 468 reg,bit = location
356 else: 477 else:
357 reg = prog.resolveReg(location, None, {}) 478 reg = prog.resolveReg(location, None, {})
358 output.append('\n\t{reg} = {val};'.format(reg=reg, val=explicit[flag])) 479 output.append('\n\t{reg} = {val};'.format(reg=reg, val=explicit[flag]))
359 return ''.join(output) 480 return ''.join(output)
360 481
361 def _cmpCImpl(prog, params): 482 def _cmpCImpl(prog, params, rawParams, flagUpdates):
362 size = prog.paramSize(params[1]) 483 size = prog.paramSize(rawParams[1])
484 needsCarry = False
485 if flagUpdates:
486 for flag in flagUpdates:
487 calc = prog.flags.flagCalc[flag]
488 if calc == 'carry':
489 needsCarry = True
490 break
491 if needsCarry:
492 size *= 2
363 tmpvar = 'cmp_tmp{sz}__'.format(sz=size) 493 tmpvar = 'cmp_tmp{sz}__'.format(sz=size)
364 typename = '' 494 if flagUpdates:
495 prog.carryFlowDst = tmpvar
496 prog.lastA = params[1]
497 prog.lastB = params[0]
498 prog.lastBFlow = params[0]
365 scope = prog.getRootScope() 499 scope = prog.getRootScope()
366 if not scope.resolveLocal(tmpvar): 500 if not scope.resolveLocal(tmpvar):
367 scope.addLocal(tmpvar, size) 501 scope.addLocal(tmpvar, size)
368 prog.lastDst = tmpvar 502 prog.lastDst = rawParams[1]
369 return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1]) 503 return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1])
370 504
371 def _asrCImpl(prog, params, rawParams): 505 def _asrCImpl(prog, params, rawParams, flagUpdates):
372 shiftSize = prog.paramSize(rawParams[0]) 506 needsCarry = False
373 mask = 1 << (shiftSize - 1) 507 if flagUpdates:
374 return '\n\t{dst} = ({a} >> {b}) | ({a} & {mask});'.format(a = params[0], b = params[1], dst = params[2], mask = mask) 508 for flag in flagUpdates:
375 509 calc = prog.flags.flagCalc[flag]
510 if calc == 'carry':
511 needsCarry = True
512 decl = ''
513 size = prog.paramSize(rawParams[2])
514 if needsCarry:
515 decl,name = prog.getTemp(size * 2)
516 dst = prog.carryFlowDst = name
517 prog.lastA = params[0]
518 else:
519 dst = params[2]
520 mask = 1 << (size - 1)
521 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)
523
524 def _sext(size, src):
525 if size == 16:
526 return src | 0xFF00 if src & 0x80 else src
527 else:
528 return src | 0xFFFF0000 if src & 0x8000 else src
529
530 def _sextCImpl(prog, params, rawParms):
531 if params[0] == 16:
532 fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src};'
533 else:
534 fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src};'
535 return fmt.format(src=params[1], dst=params[2])
536
537 def _getCarryCheck(prog):
538 carryFlag = None
539 for flag in prog.flags.flagCalc:
540 if prog.flags.flagCalc[flag] == 'carry':
541 carryFlag = flag
542 if carryFlag is None:
543 raise Exception('adc requires a defined carry flag')
544 carryStorage = prog.flags.getStorage(carryFlag)
545 if type(carryStorage) is tuple:
546 reg,bit = carryStorage
547 reg = prog.resolveReg(reg, None, (), False)
548 return '({reg} & 1 << {bit})'.format(reg=reg, bit=bit)
549 else:
550 return prog.resolveReg(carryStorage, None, (), False)
551
552 def _adcCImpl(prog, params, rawParams, flagUpdates):
553 needsCarry = needsOflow = needsHalf = False
554 if flagUpdates:
555 for flag in flagUpdates:
556 calc = prog.flags.flagCalc[flag]
557 if calc == 'carry':
558 needsCarry = True
559 elif calc == 'half-carry':
560 needsHalf = True
561 elif calc == 'overflow':
562 needsOflow = True
563 decl = ''
564 carryCheck = _getCarryCheck(prog)
565 if needsCarry or needsOflow or needsHalf:
566 size = prog.paramSize(rawParams[2])
567 if needsCarry:
568 size *= 2
569 decl,name = prog.getTemp(size)
570 dst = prog.carryFlowDst = name
571 prog.lastA = params[0]
572 prog.lastB = params[1]
573 prog.lastBFlow = '(~{b})'.format(b=params[1])
574 else:
575 dst = params[2]
576 return decl + '\n\t{dst} = {a} + {b} + ({check} ? 1 : 0);'.format(dst = dst,
577 a = params[0], b = params[1], check = carryCheck
578 )
579
580 def _sbcCImpl(prog, params, rawParams, flagUpdates):
581 needsCarry = needsOflow = needsHalf = False
582 if flagUpdates:
583 for flag in flagUpdates:
584 calc = prog.flags.flagCalc[flag]
585 if calc == 'carry':
586 needsCarry = True
587 elif calc == 'half-carry':
588 needsHalf = True
589 elif calc == 'overflow':
590 needsOflow = True
591 decl = ''
592 carryCheck = _getCarryCheck(prog)
593 if needsCarry or needsOflow or needsHalf:
594 size = prog.paramSize(rawParams[2])
595 if needsCarry:
596 size *= 2
597 decl,name = prog.getTemp(size)
598 dst = prog.carryFlowDst = name
599 prog.lastA = params[1]
600 prog.lastB = params[0]
601 prog.lastBFlow = params[0]
602 else:
603 dst = params[2]
604 return decl + '\n\t{dst} = {b} - {a} - ({check} ? 1 : 0);'.format(dst = dst,
605 a = params[0], b = params[1], check=_getCarryCheck(prog)
606 )
607
608 def _rolCImpl(prog, params, rawParams, flagUpdates):
609 needsCarry = False
610 if flagUpdates:
611 for flag in flagUpdates:
612 calc = prog.flags.flagCalc[flag]
613 if calc == 'carry':
614 needsCarry = True
615 decl = ''
616 size = prog.paramSize(rawParams[2])
617 if needsCarry:
618 decl,name = prog.getTemp(size * 2)
619 dst = prog.carryFlowDst = name
620 else:
621 dst = params[2]
622 return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} - {b});'.format(dst = dst,
623 a = params[0], b = params[1], size=size
624 )
625
626 def _rlcCImpl(prog, params, rawParams, flagUpdates):
627 needsCarry = False
628 if flagUpdates:
629 for flag in flagUpdates:
630 calc = prog.flags.flagCalc[flag]
631 if calc == 'carry':
632 needsCarry = True
633 decl = ''
634 carryCheck = _getCarryCheck(prog)
635 size = prog.paramSize(rawParams[2])
636 if needsCarry:
637 decl,name = prog.getTemp(size * 2)
638 dst = prog.carryFlowDst = name
639 else:
640 dst = params[2]
641 return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({b} - 1);'.format(dst = dst,
642 a = params[0], b = params[1], size=size, check=carryCheck
643 )
644
645 def _rorCImpl(prog, params, rawParams, flagUpdates):
646 size = prog.paramSize(rawParams[2])
647 return '\n\t{dst} = {a} >> {b} | {a} << ({size} - {b});'.format(dst = params[2],
648 a = params[0], b = params[1], size=size
649 )
650
651 def _rrcCImpl(prog, params, rawParams, flagUpdates):
652 needsCarry = False
653 if flagUpdates:
654 for flag in flagUpdates:
655 calc = prog.flags.flagCalc[flag]
656 if calc == 'carry':
657 needsCarry = True
658 decl = ''
659 carryCheck = _getCarryCheck(prog)
660 size = prog.paramSize(rawParams[2])
661 if needsCarry:
662 decl,name = prog.getTemp(size * 2)
663 dst = prog.carryFlowDst = name
664 else:
665 dst = params[2]
666 return decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({size}-{b});'.format(dst = dst,
667 a = params[0], b = params[1], size=size, check=carryCheck
668 )
669
670 def _updateSyncCImpl(prog, params):
671 return '\n\t{sync}(context, target_cycle);'.format(sync=prog.sync_cycle)
672
376 _opMap = { 673 _opMap = {
377 'mov': Op(lambda val: val).cUnaryOperator(''), 674 'mov': Op(lambda val: val).cUnaryOperator(''),
378 'not': Op(lambda val: ~val).cUnaryOperator('~'), 675 'not': Op(lambda val: ~val).cUnaryOperator('~'),
379 'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'), 676 'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'),
380 'neg': Op(lambda val: -val).cUnaryOperator('-'), 677 'neg': Op(lambda val: -val).cUnaryOperator('-'),
381 'add': Op(lambda a, b: a + b).cBinaryOperator('+'), 678 'add': Op(lambda a, b: a + b).cBinaryOperator('+'),
679 'adc': Op().addImplementation('c', 2, _adcCImpl),
382 'sub': Op(lambda a, b: b - a).cBinaryOperator('-'), 680 'sub': Op(lambda a, b: b - a).cBinaryOperator('-'),
681 'sbc': Op().addImplementation('c', 2, _sbcCImpl),
383 'lsl': Op(lambda a, b: a << b).cBinaryOperator('<<'), 682 'lsl': Op(lambda a, b: a << b).cBinaryOperator('<<'),
384 'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'), 683 'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'),
385 'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl), 684 'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl),
685 'rol': Op().addImplementation('c', 2, _rolCImpl),
686 'rlc': Op().addImplementation('c', 2, _rlcCImpl),
687 'ror': Op().addImplementation('c', 2, _rorCImpl),
688 'rrc': Op().addImplementation('c', 2, _rrcCImpl),
386 'and': Op(lambda a, b: a & b).cBinaryOperator('&'), 689 'and': Op(lambda a, b: a & b).cBinaryOperator('&'),
387 'or': Op(lambda a, b: a | b).cBinaryOperator('|'), 690 'or': Op(lambda a, b: a | b).cBinaryOperator('|'),
388 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'), 691 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'),
389 'abs': Op(lambda val: abs(val)).addImplementation( 692 '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]) 693 'c', 1, lambda prog, params: '\n\t{dst} = abs({src});'.format(dst=params[1], src=params[0])
391 ), 694 ),
392 'cmp': Op().addImplementation('c', None, _cmpCImpl), 695 'cmp': Op().addImplementation('c', None, _cmpCImpl),
696 'sext': Op(_sext).addImplementation('c', 2, _sextCImpl),
393 'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format( 697 'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format(
394 pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]]) 698 pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]])
395 )), 699 )),
396 'cycles': Op().addImplementation('c', None, 700 'cycles': Op().addImplementation('c', None,
397 lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format( 701 lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format(
408 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - {sz} ? {sz} * 2 : 1;'.format( 712 ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - {sz} ? {sz} * 2 : 1;'.format(
409 dst = params[2], sz = params[0], val = params[1] 713 dst = params[2], sz = params[0], val = params[1]
410 )), 714 )),
411 'xchg': Op().addImplementation('c', (0,1), _xchgCImpl), 715 'xchg': Op().addImplementation('c', (0,1), _xchgCImpl),
412 'dispatch': Op().addImplementation('c', None, _dispatchCImpl), 716 'dispatch': Op().addImplementation('c', None, _dispatchCImpl),
413 'update_flags': Op().addImplementation('c', None, _updateFlagsCImpl) 717 'update_flags': Op().addImplementation('c', None, _updateFlagsCImpl),
718 'update_sync': Op().addImplementation('c', None, _updateSyncCImpl)
414 } 719 }
415 720
416 #represents a simple DSL instruction 721 #represents a simple DSL instruction
417 class NormalOp: 722 class NormalOp:
418 def __init__(self, parts): 723 def __init__(self, parts):
419 self.op = parts[0] 724 self.op = parts[0]
420 self.params = parts[1:] 725 self.params = parts[1:]
421 726
422 def generate(self, prog, parent, fieldVals, output, otype): 727 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
423 procParams = [] 728 procParams = []
424 allParamsConst = True 729 allParamsConst = flagUpdates is None and not prog.conditional
425 opDef = _opMap.get(self.op) 730 opDef = _opMap.get(self.op)
426 for param in self.params: 731 for param in self.params:
427 allowConst = (self.op in prog.subroutines or len(procParams) != len(self.params) - 1) and param in parent.regValues 732 allowConst = (self.op in prog.subroutines or len(procParams) != len(self.params) - 1) and param in parent.regValues
428 isDst = (not opDef is None) and len(procParams) in opDef.outOp 733 isDst = (not opDef is None) and len(procParams) in opDef.outOp
734 if isDst and self.op == 'xchg':
735 #xchg uses its regs as both source and destination
736 #we need to resolve as both so that disperse/coalesce flag stuff gets done
737 prog.resolveParam(param, parent, fieldVals, allowConst, False)
429 param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst) 738 param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst)
430 739
431 if (not type(param) is int) and len(procParams) != len(self.params) - 1: 740 if (not type(param) is int) and len(procParams) != len(self.params) - 1:
432 allParamsConst = False 741 allParamsConst = False
433 procParams.append(param) 742 procParams.append(param)
446 prog.meta[self.params[0]] = param 755 prog.meta[self.params[0]] = param
447 elif self.op == 'dis': 756 elif self.op == 'dis':
448 #TODO: Disassembler 757 #TODO: Disassembler
449 pass 758 pass
450 elif not opDef is None: 759 elif not opDef is None:
760 if opDef.numParams() > len(procParams):
761 raise Exception('Insufficient params for ' + self.op + ' (' + ', '.join(self.params) + ')')
451 if opDef.canEval() and allParamsConst: 762 if opDef.canEval() and allParamsConst:
452 #do constant folding 763 #do constant folding
453 if opDef.numArgs() >= len(procParams): 764 if opDef.numArgs() >= len(procParams):
454 raise Exception('Insufficient args for ' + self.op + ' (' + ', '.join(self.params) + ')') 765 raise Exception('Insufficient args for ' + self.op + ' (' + ', '.join(self.params) + ')')
455 dst = self.params[opDef.numArgs()] 766 dst = self.params[opDef.numArgs()]
459 maybeLocal = parent.resolveLocal(dst) 770 maybeLocal = parent.resolveLocal(dst)
460 if maybeLocal: 771 if maybeLocal:
461 dst = maybeLocal 772 dst = maybeLocal
462 parent.regValues[dst] = result 773 parent.regValues[dst] = result
463 if prog.isReg(dst): 774 if prog.isReg(dst):
464 output.append(_opMap['mov'].generate(otype, prog, procParams, self.params)) 775 shortProc = (procParams[0], procParams[-1])
465 else: 776 shortParams = (self.params[0], self.params[-1])
466 output.append(opDef.generate(otype, prog, procParams, self.params)) 777 output.append(_opMap['mov'].generate(otype, prog, shortProc, shortParams, None))
778 else:
779 output.append(opDef.generate(otype, prog, procParams, self.params, flagUpdates))
780 for dstIdx in opDef.outOp:
781 dst = self.params[dstIdx]
782 while dst in prog.meta:
783 dst = prog.meta[dst]
784 if dst in parent.regValues:
785 del parent.regValues[dst]
786
467 elif self.op in prog.subroutines: 787 elif self.op in prog.subroutines:
788 procParams = []
789 for param in self.params:
790 begin,sep,end = param.partition('.')
791 if sep:
792 if end in fieldVals:
793 param = begin + '.' + str(fieldVals[end])
794 else:
795 if param in fieldVals:
796 param = fieldVals[param]
797 procParams.append(param)
468 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent) 798 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent)
469 else: 799 else:
470 output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');') 800 output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');')
471 prog.lastOp = self 801 prog.lastOp = self
472 802
515 def localSize(self, name): 845 def localSize(self, name):
516 if name in self.current_locals: 846 if name in self.current_locals:
517 return self.current_locals[name] 847 return self.current_locals[name]
518 return self.parent.localSize(name) 848 return self.parent.localSize(name)
519 849
520 def generate(self, prog, parent, fieldVals, output, otype): 850 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
521 prog.pushScope(self) 851 prog.pushScope(self)
522 param = prog.resolveParam(self.param, parent, fieldVals) 852 param = prog.resolveParam(self.param, parent, fieldVals)
523 if type(param) is int: 853 if type(param) is int:
524 self.regValues = self.parent.regValues 854 self.regValues = self.parent.regValues
525 if param in self.cases: 855 if param in self.cases:
526 self.current_locals = self.case_locals[param] 856 self.current_locals = self.case_locals[param]
527 output.append('\n\t{') 857 output.append('\n\t{')
528 for local in self.case_locals[param]: 858 for local in self.case_locals[param]:
529 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local)) 859 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local))
530 for op in self.cases[param]: 860 self.processOps(prog, fieldVals, output, otype, self.cases[param])
531 op.generate(prog, self, fieldVals, output, otype)
532 output.append('\n\t}') 861 output.append('\n\t}')
533 elif self.default: 862 elif self.default:
534 self.current_locals = self.default_locals 863 self.current_locals = self.default_locals
535 output.append('\n\t{') 864 output.append('\n\t{')
536 for local in self.default_locals: 865 for local in self.default_locals:
537 output.append('\n\tuint{0}_t {1};'.format(self.default[local], local)) 866 output.append('\n\tuint{0}_t {1};'.format(self.default[local], local))
538 for op in self.default: 867 self.processOps(prog, fieldVals, output, otype, self.default)
539 op.generate(prog, self, fieldVals, output, otype)
540 output.append('\n\t}') 868 output.append('\n\t}')
541 else: 869 else:
870 oldCond = prog.conditional
871 prog.conditional = True
542 output.append('\n\tswitch(' + param + ')') 872 output.append('\n\tswitch(' + param + ')')
543 output.append('\n\t{') 873 output.append('\n\t{')
544 for case in self.cases: 874 for case in self.cases:
875 temp = prog.temp.copy()
545 self.current_locals = self.case_locals[case] 876 self.current_locals = self.case_locals[case]
546 self.regValues = dict(self.parent.regValues) 877 self.regValues = dict(self.parent.regValues)
547 output.append('\n\tcase {0}U: '.format(case) + '{') 878 output.append('\n\tcase {0}U: '.format(case) + '{')
548 for local in self.case_locals[case]: 879 for local in self.case_locals[case]:
549 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[case][local], local)) 880 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[case][local], local))
550 for op in self.cases[case]: 881 self.processOps(prog, fieldVals, output, otype, self.cases[case])
551 op.generate(prog, self, fieldVals, output, otype)
552 output.append('\n\tbreak;') 882 output.append('\n\tbreak;')
553 output.append('\n\t}') 883 output.append('\n\t}')
884 prog.temp = temp
554 if self.default: 885 if self.default:
886 temp = prog.temp.copy()
555 self.current_locals = self.default_locals 887 self.current_locals = self.default_locals
556 self.regValues = dict(self.parent.regValues) 888 self.regValues = dict(self.parent.regValues)
557 output.append('\n\tdefault: {') 889 output.append('\n\tdefault: {')
558 for local in self.default_locals: 890 for local in self.default_locals:
559 output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local)) 891 output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local))
560 for op in self.default: 892 self.processOps(prog, fieldVals, output, otype, self.default)
561 op.generate(prog, self, fieldVals, output, otype) 893 prog.temp = temp
562 output.append('\n\t}') 894 output.append('\n\t}')
895 prog.conditional = oldCond
563 prog.popScope() 896 prog.popScope()
564 897
565 def __str__(self): 898 def __str__(self):
566 keys = self.cases.keys() 899 keys = self.cases.keys()
567 keys.sort() 900 keys.sort()
577 if prog.lastOp.op == 'cmp': 910 if prog.lastOp.op == 'cmp':
578 output.pop() 911 output.pop()
579 params = [prog.resolveParam(p, parent, fieldVals) for p in prog.lastOp.params] 912 params = [prog.resolveParam(p, parent, fieldVals) for p in prog.lastOp.params]
580 return '\n\tif ({a} >= {b}) '.format(a=params[1], b = params[0]) + '{' 913 return '\n\tif ({a} >= {b}) '.format(a=params[1], b = params[0]) + '{'
581 else: 914 else:
582 raise ion(">=U not implemented in the general case yet") 915 raise Exception(">=U not implemented in the general case yet")
916
917 def _eqCImpl(prog, parent, fieldVals, output):
918 return '\n\tif (!{a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {}))
919
920 def _neqCImpl(prog, parent, fieldVals, output):
921 return '\n\tif ({a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {}))
583 922
584 _ifCmpImpl = { 923 _ifCmpImpl = {
585 'c': { 924 'c': {
586 '>=U': _geuCImpl 925 '>=U': _geuCImpl,
926 '=': _eqCImpl,
927 '!=': _neqCImpl
587 } 928 }
588 } 929 }
589 #represents a DSL conditional construct 930 #represents a DSL conditional construct
590 class If(ChildBlock): 931 class If(ChildBlock):
591 def __init__(self, parent, cond): 932 def __init__(self, parent, cond):
604 if op.op in ('case', 'arg'): 945 if op.op in ('case', 'arg'):
605 raise Exception(self.op + ' is not allows inside an if block') 946 raise Exception(self.op + ' is not allows inside an if block')
606 if op.op == 'local': 947 if op.op == 'local':
607 name = op.params[0] 948 name = op.params[0]
608 size = op.params[1] 949 size = op.params[1]
609 self.locals[name] = size 950 self.curLocals[name] = size
610 elif op.op == 'else': 951 elif op.op == 'else':
611 self.curLocals = self.elseLocals 952 self.curLocals = self.elseLocals
612 self.curBody = self.elseBody 953 self.curBody = self.elseBody
613 else: 954 else:
614 self.curBody.append(op) 955 self.curBody.append(op)
615 956
616 def localSize(self, name): 957 def localSize(self, name):
617 return self.curLocals.get(name) 958 return self.curLocals.get(name)
618 959
619 def resolveLocal(self, name): 960 def resolveLocal(self, name):
620 if name in self.locals: 961 if name in self.curLocals:
621 return name 962 return name
622 return self.parent.resolveLocal(name) 963 return self.parent.resolveLocal(name)
623 964
624 def _genTrueBody(self, prog, fieldVals, output, otype): 965 def _genTrueBody(self, prog, fieldVals, output, otype):
625 self.curLocals = self.locals 966 self.curLocals = self.locals
967 subOut = []
968 self.processOps(prog, fieldVals, subOut, otype, self.body)
626 for local in self.locals: 969 for local in self.locals:
627 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.locals[local], nm=local)) 970 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.locals[local], nm=local))
628 for op in self.body: 971 output += subOut
629 op.generate(prog, self, fieldVals, output, otype)
630 972
631 def _genFalseBody(self, prog, fieldVals, output, otype): 973 def _genFalseBody(self, prog, fieldVals, output, otype):
632 self.curLocals = self.elseLocals 974 self.curLocals = self.elseLocals
975 subOut = []
976 self.processOps(prog, fieldVals, subOut, otype, self.elseBody)
633 for local in self.elseLocals: 977 for local in self.elseLocals:
634 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.elseLocals[local], nm=local)) 978 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.elseLocals[local], nm=local))
635 for op in self.elseBody: 979 output += subOut
636 op.generate(prog, self, fieldVals, output, otype)
637 980
638 def _genConstParam(self, param, prog, fieldVals, output, otype): 981 def _genConstParam(self, param, prog, fieldVals, output, otype):
639 if param: 982 if param:
640 self._genTrueBody(prog, fieldVals, output, otype) 983 self._genTrueBody(prog, fieldVals, output, otype)
641 else: 984 else:
642 self._genFalseBody(prog, fieldVals, output, otype) 985 self._genFalseBody(prog, fieldVals, output, otype)
643 986
644 def generate(self, prog, parent, fieldVals, output, otype): 987 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
645 self.regValues = parent.regValues 988 self.regValues = parent.regValues
646 try: 989 try:
647 self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype) 990 self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype)
648 except Exception: 991 except Exception:
649 if self.cond in _ifCmpImpl[otype]: 992 if self.cond in _ifCmpImpl[otype]:
993 oldCond = prog.conditional
994 prog.conditional = True
995 temp = prog.temp.copy()
650 output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output)) 996 output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output))
651 self._genTrueBody(prog, fieldVals, output, otype) 997 self._genTrueBody(prog, fieldVals, output, otype)
998 prog.temp = temp
652 if self.elseBody: 999 if self.elseBody:
1000 temp = prog.temp.copy()
653 output.append('\n\t} else {') 1001 output.append('\n\t} else {')
654 self._genFalseBody(prog, fieldVals, output, otype) 1002 self._genFalseBody(prog, fieldVals, output, otype)
1003 prog.temp = temp
655 output.append('\n\t}') 1004 output.append('\n\t}')
1005 prog.conditional = oldCond
656 else: 1006 else:
657 cond = prog.resolveParam(self.cond, parent, fieldVals) 1007 cond = prog.resolveParam(self.cond, parent, fieldVals)
658 if type(cond) is int: 1008 if type(cond) is int:
659 self._genConstParam(cond, prog, fieldVals, output, otype) 1009 self._genConstParam(cond, prog, fieldVals, output, otype)
660 else: 1010 else:
1011 temp = prog.temp.copy()
661 output.append('\n\tif ({cond}) '.format(cond=cond) + '{') 1012 output.append('\n\tif ({cond}) '.format(cond=cond) + '{')
1013 oldCond = prog.conditional
1014 prog.conditional = True
662 self._genTrueBody(prog, fieldVals, output, otype) 1015 self._genTrueBody(prog, fieldVals, output, otype)
1016 prog.temp = temp
663 if self.elseBody: 1017 if self.elseBody:
1018 temp = prog.temp.copy()
664 output.append('\n\t} else {') 1019 output.append('\n\t} else {')
665 self._genFalseBody(prog, fieldVals, output, otype) 1020 self._genFalseBody(prog, fieldVals, output, otype)
1021 prog.temp = temp
666 output.append('\n\t}') 1022 output.append('\n\t}')
1023 prog.conditional = oldCond
667 1024
668 1025
669 def __str__(self): 1026 def __str__(self):
670 lines = ['\n\tif'] 1027 lines = ['\n\tif']
671 for op in self.body: 1028 for op in self.body:
677 def __init__(self): 1034 def __init__(self):
678 self.regs = {} 1035 self.regs = {}
679 self.pointers = {} 1036 self.pointers = {}
680 self.regArrays = {} 1037 self.regArrays = {}
681 self.regToArray = {} 1038 self.regToArray = {}
1039 self.addReg('cycles', 32)
1040 self.addReg('sync_cycle', 32)
682 1041
683 def addReg(self, name, size): 1042 def addReg(self, name, size):
684 self.regs[name] = size 1043 self.regs[name] = size
685 1044
686 def addPointer(self, name, size): 1045 def addPointer(self, name, size, count):
687 self.pointers[name] = size 1046 self.pointers[name] = (size, count)
688 1047
689 def addRegArray(self, name, size, regs): 1048 def addRegArray(self, name, size, regs):
690 self.regArrays[name] = (size, regs) 1049 self.regArrays[name] = (size, regs)
691 idx = 0 1050 idx = 0
692 if not type(regs) is int: 1051 if not type(regs) is int:
719 def isNamedArray(self, array): 1078 def isNamedArray(self, array):
720 return array in self.regArrays and type(self.regArrays[array][1]) is int 1079 return array in self.regArrays and type(self.regArrays[array][1]) is int
721 1080
722 def processLine(self, parts): 1081 def processLine(self, parts):
723 if len(parts) == 3: 1082 if len(parts) == 3:
724 self.addRegArray(parts[0], int(parts[1]), int(parts[2])) 1083 if parts[1].startswith('ptr'):
1084 self.addPointer(parts[0], parts[1][3:], int(parts[2]))
1085 else:
1086 self.addRegArray(parts[0], int(parts[1]), int(parts[2]))
725 elif len(parts) > 2: 1087 elif len(parts) > 2:
726 self.addRegArray(parts[0], int(parts[1]), parts[2:]) 1088 self.addRegArray(parts[0], int(parts[1]), parts[2:])
727 else: 1089 else:
728 if parts[1].startswith('ptr'): 1090 if parts[1].startswith('ptr'):
729 self.addPointer(parts[0], int(parts[1][3:])) 1091 self.addPointer(parts[0], parts[1][3:], 1)
730 else: 1092 else:
731 self.addReg(parts[0], int(parts[1])) 1093 self.addReg(parts[0], int(parts[1]))
732 return self 1094 return self
733 1095
734 def writeHeader(self, otype, hFile): 1096 def writeHeader(self, otype, hFile):
735 fieldList = [] 1097 fieldList = []
736 for pointer in self.pointers: 1098 for pointer in self.pointers:
737 hFile.write('\n\tuint{sz}_t *{nm};'.format(nm=pointer, sz=self.pointers[pointer])) 1099 stars = '*'
1100 ptype, count = self.pointers[pointer]
1101 while ptype.startswith('ptr'):
1102 stars += '*'
1103 ptype = ptype[3:]
1104 if ptype.isdigit():
1105 ptype = 'uint{sz}_t'.format(sz=ptype)
1106 if count > 1:
1107 arr = '[{n}]'.format(n=count)
1108 else:
1109 arr = ''
1110 hFile.write('\n\t{ptype} {stars}{nm}{arr};'.format(nm=pointer, ptype=ptype, stars=stars, arr=arr))
738 for reg in self.regs: 1111 for reg in self.regs:
739 if not self.isRegArrayMember(reg): 1112 if not self.isRegArrayMember(reg):
740 fieldList.append((self.regs[reg], 1, reg)) 1113 fieldList.append((self.regs[reg], 1, reg))
741 for arr in self.regArrays: 1114 for arr in self.regArrays:
742 size,regs = self.regArrays[arr] 1115 size,regs = self.regArrays[arr]
755 def __init__(self): 1128 def __init__(self):
756 self.flagBits = {} 1129 self.flagBits = {}
757 self.flagCalc = {} 1130 self.flagCalc = {}
758 self.flagStorage = {} 1131 self.flagStorage = {}
759 self.flagReg = None 1132 self.flagReg = None
1133 self.storageToFlags = {}
760 self.maxBit = -1 1134 self.maxBit = -1
761 1135
762 def processLine(self, parts): 1136 def processLine(self, parts):
763 if parts[0] == 'register': 1137 if parts[0] == 'register':
764 self.flagReg = parts[1] 1138 self.flagReg = parts[1]
775 if bit > self.maxBit: 1149 if bit > self.maxBit:
776 self.maxBit = bit 1150 self.maxBit = bit
777 self.flagBits[flag] = bit 1151 self.flagBits[flag] = bit
778 self.flagCalc[flag] = calc 1152 self.flagCalc[flag] = calc
779 self.flagStorage[flag] = storage 1153 self.flagStorage[flag] = storage
1154 storage,_,storebit = storage.partition('.')
1155 self.storageToFlags.setdefault(storage, []).append((storebit, flag))
780 return self 1156 return self
781 1157
782 def getStorage(self, flag): 1158 def getStorage(self, flag):
783 if not flag in self.flagStorage: 1159 if not flag in self.flagStorage:
784 raise Exception('Undefined flag ' + flag) 1160 raise Exception('Undefined flag ' + flag)
785 loc,_,bit = self.flagStorage[flag].partition('.') 1161 loc,_,bit = self.flagStorage[flag].partition('.')
786 if bit: 1162 if bit:
787 return (loc, int(bit)) 1163 return (loc, int(bit))
788 else: 1164 else:
789 return loc 1165 return loc
1166
1167 def parseFlagUpdate(self, flagString):
1168 last = ''
1169 autoUpdate = set()
1170 explicit = {}
1171 for c in flagString:
1172 if c.isdigit():
1173 if last.isalpha():
1174 num = int(c)
1175 if num > 1:
1176 raise Exception(c + ' is not a valid digit for update_flags')
1177 explicit[last] = num
1178 last = c
1179 else:
1180 raise Exception('Digit must follow flag letter in update_flags')
1181 else:
1182 if last.isalpha():
1183 autoUpdate.add(last)
1184 last = c
1185 if last.isalpha():
1186 autoUpdate.add(last)
1187 return (autoUpdate, explicit)
790 1188
791 def disperseFlags(self, prog, otype): 1189 def disperseFlags(self, prog, otype):
792 bitToFlag = [None] * (self.maxBit+1) 1190 bitToFlag = [None] * (self.maxBit+1)
793 src = prog.resolveReg(self.flagReg, None, {}) 1191 src = prog.resolveReg(self.flagReg, None, {})
794 output = [] 1192 output = []
882 else: 1280 else:
883 output.append('\n\tif ({src} & (1 << {srcbit})) {{\n\t\t{dst} |= 1 << {dstbit};\n\t}}'.format( 1281 output.append('\n\tif ({src} & (1 << {srcbit})) {{\n\t\t{dst} |= 1 << {dstbit};\n\t}}'.format(
884 src=src, dst=dst, srcbit=srcbit, dstbit=dstbit 1282 src=src, dst=dst, srcbit=srcbit, dstbit=dstbit
885 )) 1283 ))
886 if direct: 1284 if direct:
887 output.append('\n\t{dst} |= {src} & {mask}'.format( 1285 output.append('\n\t{dst} |= {src} & {mask};'.format(
888 dst=dst, src=src, mask=direct 1286 dst=dst, src=src, mask=direct
889 )) 1287 ))
890 return ''.join(output) 1288 return ''.join(output)
891 1289
892 1290
900 self.prefix = info.get('prefix', [''])[0] 1298 self.prefix = info.get('prefix', [''])[0]
901 self.opsize = int(info.get('opcode_size', ['8'])[0]) 1299 self.opsize = int(info.get('opcode_size', ['8'])[0])
902 self.extra_tables = info.get('extra_tables', []) 1300 self.extra_tables = info.get('extra_tables', [])
903 self.context_type = self.prefix + 'context' 1301 self.context_type = self.prefix + 'context'
904 self.body = info.get('body', [None])[0] 1302 self.body = info.get('body', [None])[0]
1303 self.interrupt = info.get('interrupt', [None])[0]
1304 self.sync_cycle = info.get('sync_cycle', [None])[0]
905 self.includes = info.get('include', []) 1305 self.includes = info.get('include', [])
906 self.flags = flags 1306 self.flags = flags
907 self.lastDst = None 1307 self.lastDst = None
908 self.scopes = [] 1308 self.scopes = []
909 self.currentScope = None 1309 self.currentScope = None
910 self.lastOp = None 1310 self.lastOp = None
1311 self.carryFlowDst = None
1312 self.lastA = None
1313 self.lastB = None
1314 self.lastBFlow = None
1315 self.conditional = False
1316 self.declares = []
911 1317
912 def __str__(self): 1318 def __str__(self):
913 pieces = [] 1319 pieces = []
914 for reg in self.regs: 1320 for reg in self.regs:
915 pieces.append(str(self.regs[reg])) 1321 pieces.append(str(self.regs[reg]))
928 hFile.write('\n\ntypedef struct {') 1334 hFile.write('\n\ntypedef struct {')
929 hFile.write('\n\tcpu_options gen;') 1335 hFile.write('\n\tcpu_options gen;')
930 hFile.write('\n}} {0}options;'.format(self.prefix)) 1336 hFile.write('\n}} {0}options;'.format(self.prefix))
931 hFile.write('\n\ntypedef struct {') 1337 hFile.write('\n\ntypedef struct {')
932 hFile.write('\n\t{0}options *opts;'.format(self.prefix)) 1338 hFile.write('\n\t{0}options *opts;'.format(self.prefix))
933 hFile.write('\n\tuint32_t cycles;')
934 self.regs.writeHeader(otype, hFile) 1339 self.regs.writeHeader(otype, hFile)
935 hFile.write('\n}} {0}context;'.format(self.prefix)) 1340 hFile.write('\n}} {0}context;'.format(self.prefix))
936 hFile.write('\n') 1341 hFile.write('\n')
1342 hFile.write('\nvoid {pre}execute({type} *context, uint32_t target_cycle);'.format(pre = self.prefix, type = self.context_type))
1343 for decl in self.declares:
1344 hFile.write('\n' + decl)
937 hFile.write('\n#endif //{0}_'.format(macro)) 1345 hFile.write('\n#endif //{0}_'.format(macro))
938 hFile.write('\n') 1346 hFile.write('\n')
939 hFile.close() 1347 hFile.close()
940 def build(self, otype): 1348
941 body = [] 1349 def _buildTable(self, otype, table, body, lateBody):
942 pieces = [] 1350 pieces = []
943 for include in self.includes: 1351 opmap = [None] * (1 << self.opsize)
944 body.append('#include "{0}"\n'.format(include)) 1352 bodymap = {}
945 for table in self.instructions: 1353 if table in self.instructions:
946 opmap = [None] * (1 << self.opsize)
947 bodymap = {}
948 instructions = self.instructions[table] 1354 instructions = self.instructions[table]
949 instructions.sort() 1355 instructions.sort()
950 for inst in instructions: 1356 for inst in instructions:
951 for val in inst.allValues(): 1357 for val in inst.allValues():
952 if opmap[val] is None: 1358 if opmap[val] is None:
955 self.needFlagCoalesce = False 1361 self.needFlagCoalesce = False
956 self.needFlagDisperse = False 1362 self.needFlagDisperse = False
957 self.lastOp = None 1363 self.lastOp = None
958 opmap[val] = inst.generateName(val) 1364 opmap[val] = inst.generateName(val)
959 bodymap[val] = inst.generateBody(val, self, otype) 1365 bodymap[val] = inst.generateBody(val, self, otype)
960 1366
961 pieces.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix)) 1367 if self.dispatch == 'call':
962 pieces.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap))) 1368 pieces.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
963 for inst in range(0, len(opmap)): 1369 for inst in range(0, len(opmap)):
964 op = opmap[inst] 1370 op = opmap[inst]
965 if op is None: 1371 if op is None:
966 pieces.append('\n\tunimplemented,') 1372 pieces.append('\n\tunimplemented,')
967 else: 1373 else:
968 pieces.append('\n\t' + op + ',') 1374 pieces.append('\n\t' + op + ',')
969 body.append(bodymap[inst]) 1375 body.append(bodymap[inst])
970 pieces.append('\n};') 1376 pieces.append('\n};')
971 if self.body in self.subroutines: 1377 elif self.dispatch == 'goto':
1378 body.append('\n\tstatic void *impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
1379 for inst in range(0, len(opmap)):
1380 op = opmap[inst]
1381 if op is None:
1382 body.append('\n\t\t&&unimplemented,')
1383 else:
1384 body.append('\n\t\t&&' + op + ',')
1385 lateBody.append(bodymap[inst])
1386 body.append('\n\t};')
1387 else:
1388 raise Exception("unimplmeneted dispatch type " + self.dispatch)
1389 body.extend(pieces)
1390
1391 def nextInstruction(self, otype):
1392 output = []
1393 if self.dispatch == 'goto':
1394 if self.interrupt in self.subroutines:
1395 output.append('\n\tif (context->cycles >= context->sync_cycle) {')
1396 output.append('\n\tif (context->cycles >= target_cycle) { return; }')
1397 if self.interrupt in self.subroutines:
1398 self.meta = {}
1399 self.temp = {}
1400 self.subroutines[self.interrupt].inline(self, [], output, otype, None)
1401 output.append('\n\t}')
1402
1403 self.meta = {}
1404 self.temp = {}
1405 self.subroutines[self.body].inline(self, [], output, otype, None)
1406 return output
1407
1408 def build(self, otype):
1409 body = []
1410 pieces = []
1411 for include in self.includes:
1412 body.append('#include "{0}"\n'.format(include))
1413 if self.dispatch == 'call':
1414 body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix))
1415 body.append('\n{')
1416 body.append('\n\tfatal_error("Unimplemented instruction\\n");')
1417 body.append('\n}\n')
1418 body.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix))
1419 for table in self.extra_tables:
1420 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)))
1422 elif self.dispatch == 'goto':
1423 body.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type))
1424 body.append('\n{')
1425
1426 for table in self.extra_tables:
1427 self._buildTable(otype, table, body, pieces)
1428 self._buildTable(otype, 'main', body, pieces)
1429 if self.dispatch == 'call' and self.body in self.subroutines:
972 pieces.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type)) 1430 pieces.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type))
973 pieces.append('\n{') 1431 pieces.append('\n{')
1432 pieces.append('\n\t{sync}(context, target_cycle);'.format(sync=self.sync_cycle))
974 pieces.append('\n\twhile (context->cycles < target_cycle)') 1433 pieces.append('\n\twhile (context->cycles < target_cycle)')
975 pieces.append('\n\t{') 1434 pieces.append('\n\t{')
1435 #TODO: Handle interrupts in call dispatch mode
976 self.meta = {} 1436 self.meta = {}
977 self.temp = {} 1437 self.temp = {}
978 self.subroutines[self.body].inline(self, [], pieces, otype, None) 1438 self.subroutines[self.body].inline(self, [], pieces, otype, None)
979 pieces.append('\n\t}') 1439 pieces.append('\n\t}')
980 pieces.append('\n}') 1440 pieces.append('\n}')
981 body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix)) 1441 elif self.dispatch == 'goto':
982 body.append('\n{') 1442 body.append('\n\t{sync}(context, target_cycle);'.format(sync=self.sync_cycle))
983 body.append('\n\tfatal_error("Unimplemented instruction");') 1443 body += self.nextInstruction(otype)
984 body.append('\n}\n') 1444 pieces.append('\nunimplemented:')
1445 pieces.append('\n\tfatal_error("Unimplemented instruction\\n");')
1446 pieces.append('\n}')
985 return ''.join(body) + ''.join(pieces) 1447 return ''.join(body) + ''.join(pieces)
986 1448
987 def checkBool(self, name): 1449 def checkBool(self, name):
988 if not name in self.booleans: 1450 if not name in self.booleans:
989 raise Exception(name + ' is not a defined boolean flag') 1451 raise Exception(name + ' is not a defined boolean flag')
990 return self.booleans[name] 1452 return self.booleans[name]
991 1453
992 def getTemp(self, size): 1454 def getTemp(self, size):
993 if size in self.temp: 1455 if size in self.temp:
994 return ('', self.temp[size]) 1456 return ('', self.temp[size])
995 self.temp[size] = 'tmp{sz}'.format(sz=size); 1457 self.temp[size] = 'gen_tmp{sz}__'.format(sz=size);
996 return ('\n\tuint{sz}_t tmp{sz};'.format(sz=size), self.temp[size]) 1458 return ('\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size), self.temp[size])
997 1459
998 def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False): 1460 def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False):
999 keepGoing = True 1461 keepGoing = True
1000 while keepGoing: 1462 while keepGoing:
1001 keepGoing = False 1463 keepGoing = False
1011 if parent: 1473 if parent:
1012 if param in parent.regValues and allowConstant: 1474 if param in parent.regValues and allowConstant:
1013 return parent.regValues[param] 1475 return parent.regValues[param]
1014 maybeLocal = parent.resolveLocal(param) 1476 maybeLocal = parent.resolveLocal(param)
1015 if maybeLocal: 1477 if maybeLocal:
1478 if isdst:
1479 self.lastDst = param
1016 return maybeLocal 1480 return maybeLocal
1017 if param in fieldVals: 1481 if param in fieldVals:
1018 param = fieldVals[param] 1482 param = fieldVals[param]
1483 fieldVals = {}
1484 keepGoing = True
1019 elif param in self.meta: 1485 elif param in self.meta:
1020 param = self.meta[param] 1486 param = self.meta[param]
1021 keepGoing = True 1487 keepGoing = True
1022 elif self.isReg(param): 1488 elif self.isReg(param):
1023 param = self.resolveReg(param, parent, fieldVals, isdst) 1489 return self.resolveReg(param, parent, fieldVals, isdst)
1490 if isdst:
1491 self.lastDst = param
1024 return param 1492 return param
1025 1493
1026 def isReg(self, name): 1494 def isReg(self, name):
1027 if not type(name) is str: 1495 if not type(name) is str:
1028 return False 1496 return False
1068 return ret 1536 return ret
1069 1537
1070 1538
1071 1539
1072 def paramSize(self, name): 1540 def paramSize(self, name):
1073 size = self.currentScope.localSize(name) 1541 if name in self.meta:
1074 if size: 1542 return self.paramSize(self.meta[name])
1075 return size 1543 for i in range(len(self.scopes) -1, -1, -1):
1544 size = self.scopes[i].localSize(name)
1545 if size:
1546 return size
1076 begin,sep,_ = name.partition('.') 1547 begin,sep,_ = name.partition('.')
1077 if sep and self.regs.isRegArray(begin): 1548 if sep and self.regs.isRegArray(begin):
1078 return self.regs.regArrays[begin][0] 1549 return self.regs.regArrays[begin][0]
1079 if self.regs.isReg(name): 1550 if self.regs.isReg(name):
1080 return self.regs.regs[name] 1551 return self.regs.regs[name]
1090 return ret 1561 return ret
1091 1562
1092 def getRootScope(self): 1563 def getRootScope(self):
1093 return self.scopes[0] 1564 return self.scopes[0]
1094 1565
1095 def parse(f): 1566 def parse(args):
1567 f = args.source
1096 instructions = {} 1568 instructions = {}
1097 subroutines = {} 1569 subroutines = {}
1098 registers = None 1570 registers = None
1099 flags = None 1571 flags = None
1572 declares = []
1100 errors = [] 1573 errors = []
1101 info = {} 1574 info = {}
1102 line_num = 0 1575 line_num = 0
1103 cur_object = None 1576 cur_object = None
1104 for line in f: 1577 for line in f:
1106 line,_,comment = line.partition('#') 1579 line,_,comment = line.partition('#')
1107 if not line.strip(): 1580 if not line.strip():
1108 continue 1581 continue
1109 if line[0].isspace(): 1582 if line[0].isspace():
1110 if not cur_object is None: 1583 if not cur_object is None:
1111 parts = [el.strip() for el in line.split(' ')] 1584 sep = True
1585 parts = []
1586 while sep:
1587 before,sep,after = line.partition('"')
1588 before = before.strip()
1589 if before:
1590 parts += [el.strip() for el in before.split(' ')]
1591 if sep:
1592 #TODO: deal with escaped quotes
1593 inside,sep,after = after.partition('"')
1594 parts.append('"' + inside + '"')
1595 line = after
1112 if type(cur_object) is dict: 1596 if type(cur_object) is dict:
1113 cur_object[parts[0]] = parts[1:] 1597 cur_object[parts[0]] = parts[1:]
1598 elif type(cur_object) is list:
1599 cur_object.append(' '.join(parts))
1114 else: 1600 else:
1115 cur_object = cur_object.processLine(parts) 1601 cur_object = cur_object.processLine(parts)
1116 1602
1117 # if type(cur_object) is Registers: 1603 # if type(cur_object) is Registers:
1118 # if len(parts) > 2: 1604 # if len(parts) > 2:
1166 cur_object = info 1652 cur_object = info
1167 elif line.strip() == 'flags': 1653 elif line.strip() == 'flags':
1168 if flags is None: 1654 if flags is None:
1169 flags = Flags() 1655 flags = Flags()
1170 cur_object = flags 1656 cur_object = flags
1657 elif line.strip() == 'declare':
1658 cur_object = declares
1171 else: 1659 else:
1172 cur_object = SubRoutine(line.strip()) 1660 cur_object = SubRoutine(line.strip())
1173 subroutines[cur_object.name] = cur_object 1661 subroutines[cur_object.name] = cur_object
1174 if errors: 1662 if errors:
1175 print(errors) 1663 print(errors)
1176 else: 1664 else:
1177 p = Program(registers, instructions, subroutines, info, flags) 1665 p = Program(registers, instructions, subroutines, info, flags)
1666 p.dispatch = args.dispatch
1667 p.declares = declares
1178 p.booleans['dynarec'] = False 1668 p.booleans['dynarec'] = False
1179 p.booleans['interp'] = True 1669 p.booleans['interp'] = True
1670 if args.define:
1671 for define in args.define:
1672 name,sep,val = define.partition('=')
1673 name = name.strip()
1674 val = val.strip()
1675 if sep:
1676 p.booleans[name] = bool(val)
1677 else:
1678 p.booleans[name] = True
1180 1679
1181 if 'header' in info: 1680 if 'header' in info:
1182 print('#include "{0}"'.format(info['header'][0])) 1681 print('#include "{0}"'.format(info['header'][0]))
1183 p.writeHeader('c', info['header'][0]) 1682 p.writeHeader('c', info['header'][0])
1184 print('#include "util.h"') 1683 print('#include "util.h"')
1185 print('#include <stdlib.h>') 1684 print('#include <stdlib.h>')
1186 print(p.build('c')) 1685 print(p.build('c'))
1187 1686
1188 def main(argv): 1687 def main(argv):
1189 f = open(argv[1]) 1688 from argparse import ArgumentParser, FileType
1190 parse(f) 1689 argParser = ArgumentParser(description='CPU emulator DSL compiler')
1690 argParser.add_argument('source', type=FileType('r'))
1691 argParser.add_argument('-D', '--define', action='append')
1692 argParser.add_argument('-d', '--dispatch', choices=('call', 'switch', 'goto'), default='call')
1693 parse(argParser.parse_args(argv[1:]))
1191 1694
1192 if __name__ == '__main__': 1695 if __name__ == '__main__':
1193 from sys import argv 1696 from sys import argv
1194 main(argv) 1697 main(argv)