comparison cpu_dsl.py @ 2053:3414a4423de1 segacd

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 15 Jan 2022 13:15:21 -0800
parents 7d4df6b74263
children 338c78da3fff
comparison
equal deleted inserted replaced
1692:5dacaef602a7 2053:3414a4423de1
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 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)
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):
27 def processLine(self, parts): 35 def processLine(self, parts):
38 self.implementation = [] 46 self.implementation = []
39 self.locals = {} 47 self.locals = {}
40 self.regValues = {} 48 self.regValues = {}
41 self.varyingBits = 0 49 self.varyingBits = 0
42 self.invalidFieldValues = {} 50 self.invalidFieldValues = {}
51 self.invalidCombos = []
43 self.newLocals = [] 52 self.newLocals = []
44 for field in fields: 53 for field in fields:
45 self.varyingBits += fields[field][1] 54 self.varyingBits += fields[field][1]
46 55
47 def addOp(self, op): 56 def addOp(self, op):
48 if op.op == 'local': 57 if op.op == 'local':
49 name = op.params[0] 58 name = op.params[0]
50 size = op.params[1] 59 size = int(op.params[1])
51 self.locals[name] = size 60 self.locals[name] = size
52 elif op.op == 'invalid': 61 elif op.op == 'invalid':
53 name = op.params[0] 62 if len(op.params) < 3:
54 value = int(op.params[1]) 63 name = op.params[0]
55 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)
56 else: 73 else:
57 self.implementation.append(op) 74 self.implementation.append(op)
58 75
59 def resolveLocal(self, name): 76 def resolveLocal(self, name):
60 if name in self.locals: 77 if name in self.locals:
79 def allValues(self): 96 def allValues(self):
80 values = [] 97 values = []
81 for i in range(0, 1 << self.varyingBits): 98 for i in range(0, 1 << self.varyingBits):
82 iword = self.value 99 iword = self.value
83 doIt = True 100 doIt = True
101 combos = []
102 for combo in self.invalidCombos:
103 combos.append(dict(combo))
84 for field in self.fields: 104 for field in self.fields:
85 shift,bits = self.fields[field] 105 shift,bits = self.fields[field]
86 val = i & ((1 << bits) - 1) 106 val = i & ((1 << bits) - 1)
87 if field in self.invalidFieldValues and val in self.invalidFieldValues[field]: 107 if field in self.invalidFieldValues and val in self.invalidFieldValues[field]:
88 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:
89 break 123 break
90 i >>= bits 124 i >>= bits
91 iword |= val << shift 125 iword |= val << shift
92 if doIt: 126 if doIt:
93 values.append(iword) 127 values.append(iword)
119 self.regValues = {} 153 self.regValues = {}
120 for var in self.locals: 154 for var in self.locals:
121 output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)) 155 output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var))
122 self.newLocals = [] 156 self.newLocals = []
123 fieldVals,_ = self.getFieldVals(value) 157 fieldVals,_ = self.getFieldVals(value)
124 for op in self.implementation: 158 self.processOps(prog, fieldVals, output, otype, self.implementation)
125 op.generate(prog, self, fieldVals, output, otype) 159
126 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{' 160 if prog.dispatch == 'call':
161 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context, uint32_t target_cycle)\n{'
162 elif prog.dispatch == 'goto':
163 begin = '\n' + self.generateName(value) + ': {'
164 else:
165 raise Exception('Unsupported dispatch type ' + prog.dispatch)
127 if prog.needFlagCoalesce: 166 if prog.needFlagCoalesce:
128 begin += prog.flags.coalesceFlags(prog, otype) 167 begin += prog.flags.coalesceFlags(prog, otype)
129 if prog.needFlagDisperse: 168 if prog.needFlagDisperse:
130 output.append(prog.flags.disperseFlags(prog, otype)) 169 output.append(prog.flags.disperseFlags(prog, otype))
131 for var in self.newLocals: 170 for var in self.newLocals:
132 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)
133 prog.popScope() 174 prog.popScope()
175 if prog.dispatch == 'goto':
176 output += prog.nextInstruction(otype)
134 return begin + ''.join(output) + '\n}' 177 return begin + ''.join(output) + '\n}'
135 178
136 def __str__(self): 179 def __str__(self):
137 pieces = [self.name + ' ' + hex(self.value) + ' ' + str(self.fields)] 180 pieces = [self.name + ' ' + hex(self.value) + ' ' + str(self.fields)]
138 for name in self.locals: 181 for name in self.locals:
148 self.implementation = [] 191 self.implementation = []
149 self.args = [] 192 self.args = []
150 self.arg_map = {} 193 self.arg_map = {}
151 self.locals = {} 194 self.locals = {}
152 self.regValues = {} 195 self.regValues = {}
196 self.argValues = {}
153 197
154 def addOp(self, op): 198 def addOp(self, op):
155 if op.op == 'arg': 199 if op.op == 'arg':
156 name = op.params[0] 200 name = op.params[0]
157 size = op.params[1] 201 size = int(op.params[1])
158 self.arg_map[name] = len(self.args) 202 self.arg_map[name] = len(self.args)
159 self.args.append((name, size)) 203 self.args.append((name, size))
160 elif op.op == 'local': 204 elif op.op == 'local':
161 name = op.params[0] 205 name = op.params[0]
162 size = op.params[1] 206 size = int(op.params[1])
163 self.locals[name] = size 207 self.locals[name] = size
164 else: 208 else:
165 self.implementation.append(op) 209 self.implementation.append(op)
166 210
167 def resolveLocal(self, name): 211 def resolveLocal(self, name):
171 215
172 def addLocal(self, name, size): 216 def addLocal(self, name, size):
173 self.locals[name] = size 217 self.locals[name] = size
174 218
175 def localSize(self, name): 219 def localSize(self, name):
176 return self.locals.get(name) 220 if name in self.locals:
221 return self.locals[name]
222 if name in self.arg_map:
223 argIndex = self.arg_map[name]
224 return self.args[argIndex][1]
225 return None
177 226
178 def inline(self, prog, params, output, otype, parent): 227 def inline(self, prog, params, output, otype, parent):
179 if len(params) != len(self.args): 228 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))) 229 raise Exception('{0} expects {1} arguments, but was called with {2}'.format(self.name, len(self.args), len(params)))
181 argValues = {} 230 argValues = {}
187 argValues[name] = params[i] 236 argValues[name] = params[i]
188 i += 1 237 i += 1
189 for name in self.locals: 238 for name in self.locals:
190 size = self.locals[name] 239 size = self.locals[name]
191 output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name)) 240 output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name))
192 for op in self.implementation: 241 self.argValues = argValues
193 op.generate(prog, self, argValues, output, otype) 242 self.processOps(prog, argValues, output, otype, self.implementation)
194 prog.popScope() 243 prog.popScope()
195 244
196 def __str__(self): 245 def __str__(self):
197 pieces = [self.name] 246 pieces = [self.name]
198 for name,size in self.args: 247 for name,size in self.args:
207 def __init__(self, evalFun = None): 256 def __init__(self, evalFun = None):
208 self.evalFun = evalFun 257 self.evalFun = evalFun
209 self.impls = {} 258 self.impls = {}
210 self.outOp = () 259 self.outOp = ()
211 def cBinaryOperator(self, op): 260 def cBinaryOperator(self, op):
212 def _impl(prog, params): 261 def _impl(prog, params, rawParams, flagUpdates):
213 if op == '-': 262 if op == '-':
214 a = params[1] 263 a = params[1]
215 b = params[0] 264 b = params[0]
216 else: 265 else:
217 a = params[0] 266 a = params[0]
218 b = params[1] 267 b = params[1]
219 return '\n\t{dst} = {a} {op} {b};'.format( 268 needsSizeAdjust = False
220 dst = params[2], a = a, b = b, op = op 269 if len(params) > 3:
221 ) 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
282 needsCarry = needsOflow = needsHalf = False
283 if flagUpdates:
284 for flag in flagUpdates:
285 calc = prog.flags.flagCalc[flag]
286 if calc == 'carry':
287 needsCarry = True
288 elif calc == 'half-carry':
289 needsHalf = True
290 elif calc == 'overflow':
291 needsOflow = True
292 decl = ''
293 if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust):
294 if len(params) <= 3:
295 size = prog.paramSize(rawParams[2])
296 if needsCarry and op != 'lsr':
297 size *= 2
298 decl,name = prog.getTemp(size)
299 dst = prog.carryFlowDst = name
300 prog.lastA = a
301 prog.lastB = b
302 if size == 64:
303 a = '((uint64_t){a})'.format(a=a)
304 b = '((uint64_t){b})'.format(b=b)
305 prog.lastBFlow = b if op == '-' else '(~{b})'.format(b=b)
306 elif needsSizeAdjust:
307 decl,name = prog.getTemp(size)
308 dst = params[2]
309 return '{decl}\n\t{tmp} = ({a} & {mask}) {op} ({b} & {mask});\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format(
310 decl = decl, tmp = name, a = a, b = b, op = op, dst = dst, mask = ((1 << size) - 1)
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 )
222 self.impls['c'] = _impl 322 self.impls['c'] = _impl
223 self.outOp = (2,) 323 self.outOp = (2,)
224 return self 324 return self
225 def cUnaryOperator(self, op): 325 def cUnaryOperator(self, op):
226 def _impl(prog, params): 326 def _impl(prog, params, rawParams, flagUpdates):
227 return '\n\t{dst} = {op}{a};'.format( 327 dst = params[1]
228 dst = params[1], a = params[0], op = op 328 decl = ''
229 ) 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
343 if op == '-':
344 if flagUpdates:
345 for flag in flagUpdates:
346 calc = prog.flags.flagCalc[flag]
347 if calc == 'carry':
348 needsCarry = True
349 elif calc == 'half-carry':
350 needsHalf = True
351 elif calc == 'overflow':
352 needsOflow = True
353 if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust):
354 size = prog.paramSize(rawParams[1])
355 if needsCarry:
356 size *= 2
357 decl,name = prog.getTemp(size)
358 dst = prog.carryFlowDst = name
359 prog.lastA = 0
360 prog.lastB = params[0]
361 prog.lastBFlow = params[0]
362 if needsSizeAdjust:
363 return decl + '\n\t{dst} = ({dst} & ~{mask}) | (({op}{a}) & {mask});'.format(
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 )
230 self.impls['c'] = _impl 370 self.impls['c'] = _impl
231 self.outOp = (1,) 371 self.outOp = (1,)
232 return self 372 return self
233 def addImplementation(self, lang, outOp, impl): 373 def addImplementation(self, lang, outOp, impl):
234 self.impls[lang] = impl 374 self.impls[lang] = impl
242 return self.evalFun(*params) 382 return self.evalFun(*params)
243 def canEval(self): 383 def canEval(self):
244 return not self.evalFun is None 384 return not self.evalFun is None
245 def numArgs(self): 385 def numArgs(self):
246 return self.evalFun.__code__.co_argcount 386 return self.evalFun.__code__.co_argcount
247 def generate(self, otype, prog, params, rawParams): 387 def numParams(self):
388 if self.outOp:
389 params = max(self.outOp) + 1
390 else:
391 params = 0
392 if self.evalFun:
393 params = max(params, self.numArgs())
394 return params
395 def generate(self, otype, prog, params, rawParams, flagUpdates):
248 if self.impls[otype].__code__.co_argcount == 2: 396 if self.impls[otype].__code__.co_argcount == 2:
249 return self.impls[otype](prog, params) 397 return self.impls[otype](prog, params)
250 else: 398 elif self.impls[otype].__code__.co_argcount == 3:
251 return self.impls[otype](prog, params, rawParams) 399 return self.impls[otype](prog, params, rawParams)
400 else:
401 return self.impls[otype](prog, params, rawParams, flagUpdates)
252 402
253 403
254 def _xchgCImpl(prog, params, rawParams): 404 def _xchgCImpl(prog, params, rawParams):
255 size = prog.paramSize(rawParams[0]) 405 size = prog.paramSize(rawParams[0])
256 decl,name = prog.getTemp(size) 406 decl,name = prog.getTemp(size)
259 def _dispatchCImpl(prog, params): 409 def _dispatchCImpl(prog, params):
260 if len(params) == 1: 410 if len(params) == 1:
261 table = 'main' 411 table = 'main'
262 else: 412 else:
263 table = params[1] 413 table = params[1]
264 return '\n\timpl_{tbl}[{op}](context);'.format(tbl = table, op = params[0]) 414 if prog.dispatch == 'call':
415 return '\n\timpl_{tbl}[{op}](context, target_cycle);'.format(tbl = table, op = params[0])
416 elif prog.dispatch == 'goto':
417 return '\n\tgoto *impl_{tbl}[{op}];'.format(tbl = table, op = params[0])
418 else:
419 raise Exception('Unsupported dispatch type ' + prog.dispatch)
265 420
266 def _updateFlagsCImpl(prog, params, rawParams): 421 def _updateFlagsCImpl(prog, params, rawParams):
267 i = 0 422 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 = [] 423 output = []
288 #TODO: handle autoUpdate flags 424 parity = None
425 directFlags = {}
289 for flag in autoUpdate: 426 for flag in autoUpdate:
290 calc = prog.flags.flagCalc[flag] 427 calc = prog.flags.flagCalc[flag]
291 calc,_,resultBit = calc.partition('-') 428 calc,_,resultBit = calc.partition('-')
292 lastDst = prog.resolveParam(prog.lastDst, None, {}) 429 if prog.carryFlowDst:
430 lastDst = prog.carryFlowDst
431 else:
432 lastDst = prog.resolveParam(prog.lastDst, prog.currentScope, {})
293 storage = prog.flags.getStorage(flag) 433 storage = prog.flags.getStorage(flag)
294 if calc == 'bit' or calc == 'sign': 434 if calc == 'bit' or calc == 'sign' or calc == 'carry' or calc == 'half' or calc == 'overflow':
435 myRes = lastDst
295 if calc == 'sign': 436 if calc == 'sign':
296 resultBit = prog.paramSize(prog.lastDst) - 1 437 resultBit = prog.getLastSize() - 1
297 else: 438 elif calc == 'carry':
298 resultBit = int(resultBit) 439 if prog.lastOp.op in ('asr', 'lsr'):
440 resultBit = 0
441 myRes = prog.lastA
442 else:
443 resultBit = prog.getLastSize()
444 if prog.lastOp.op == 'ror':
445 resultBit -= 1
446 elif calc == 'half':
447 resultBit = prog.getLastSize() - 4
448 myRes = '({a} ^ {b} ^ {res})'.format(a = prog.lastA, b = prog.lastB, res = lastDst)
449 elif calc == 'overflow':
450 resultBit = prog.getLastSize() - 1
451 myRes = '((({a} ^ {b})) & ({a} ^ {res}))'.format(a = prog.lastA, b = prog.lastBFlow, res = lastDst)
452 else:
453 #Note: offsetting this by the operation size - 8 makes sense for the Z80
454 #but might not for other CPUs with this kind of fixed bit flag behavior
455 resultBit = int(resultBit) + prog.getLastSize() - 8
299 if type(storage) is tuple: 456 if type(storage) is tuple:
300 reg,storageBit = storage 457 reg,storageBit = storage
301 reg = prog.resolveParam(reg, None, {})
302 if storageBit == resultBit: 458 if storageBit == resultBit:
303 #TODO: optimize this case 459 directFlags.setdefault((reg, myRes), []).append(resultBit)
304 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format( 460 else:
305 reg = reg, mask = 1 << resultBit, res = lastDst 461 reg = prog.resolveParam(reg, None, {})
306 ))
307 else:
308 if resultBit > storageBit: 462 if resultBit > storageBit:
309 op = '>>' 463 op = '>>'
310 shift = resultBit - storageBit 464 shift = resultBit - storageBit
311 else: 465 else:
312 op = '<<' 466 op = '<<'
313 shift = storageBit - resultBit 467 shift = storageBit - resultBit
314 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} {op} {shift}U & {mask}U);'.format( 468 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 469 reg = reg, mask = 1 << storageBit, res = myRes, op = op, shift = shift
316 )) 470 ))
317 else: 471 else:
318 reg = prog.resolveParam(storage, None, {}) 472 reg = prog.resolveParam(storage, None, {})
319 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=lastDst, mask = 1 << resultBit)) 473 maxBit = prog.paramSize(storage) - 1
474 if resultBit > maxBit:
475 output.append('\n\t{reg} = {res} >> {shift} & {mask}U;'.format(reg=reg, res=myRes, shift = resultBit - maxBit, mask = 1 << maxBit))
476 else:
477 output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit))
320 elif calc == 'zero': 478 elif calc == 'zero':
479 if prog.carryFlowDst:
480 realSize = prog.getLastSize()
481 if realSize != prog.paramSize(prog.carryFlowDst):
482 lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1)
321 if type(storage) is tuple: 483 if type(storage) is tuple:
322 reg,storageBit = storage 484 reg,storageBit = storage
323 reg = prog.resolveParam(reg, None, {}) 485 reg = prog.resolveParam(reg, None, {})
324 output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format( 486 output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format(
325 reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit 487 reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit
326 )) 488 ))
327 elif prog.paramSize(prog.lastDst) > prog.paramSize(storage): 489 else:
328 reg = prog.resolveParam(storage, None, {}) 490 reg = prog.resolveParam(storage, None, {})
329 output.append('\n\t{reg} = {res} != 0;'.format( 491 output.append('\n\t{reg} = {res} == 0;'.format(
330 reg = reg, res = lastDst 492 reg = reg, res = lastDst
331 )) 493 ))
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': 494 elif calc == 'parity':
342 pass 495 parity = storage
496 paritySize = prog.getLastSize()
497 if prog.carryFlowDst:
498 parityDst = paritySrc = prog.carryFlowDst
499 else:
500 paritySrc = lastDst
501 decl,name = prog.getTemp(paritySize)
502 output.append(decl)
503 parityDst = name
504 else:
505 raise Exception('Unknown flag calc type: ' + calc)
506 for reg, myRes in directFlags:
507 bits = directFlags[(reg, myRes)]
508 resolved = prog.resolveParam(reg, None, {})
509 if len(bits) == len(prog.flags.storageToFlags[reg]):
510 output.append('\n\t{reg} = {res};'.format(reg = resolved, res = myRes))
511 else:
512 mask = 0
513 for bit in bits:
514 mask |= 1 << bit
515 output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format(
516 reg = resolved, mask = mask, res = myRes
517 ))
518 if prog.carryFlowDst:
519 if prog.lastOp.op != 'cmp':
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))
527 prog.carryFlowDst = None
528 if parity:
529 if paritySize > 8:
530 if paritySize > 16:
531 output.append('\n\t{dst} = {src} ^ ({src} >> 16);'.format(dst=parityDst, src=paritySrc))
532 paritySrc = parityDst
533 output.append('\n\t{dst} = {src} ^ ({src} >> 8);'.format(dst=parityDst, src=paritySrc))
534 paritySrc = parityDst
535 output.append('\n\t{dst} = ({src} ^ ({src} >> 4)) & 0xF;'.format(dst=parityDst, src=paritySrc))
536 if type(parity) is tuple:
537 reg,bit = parity
538 reg = prog.resolveParam(reg, None, {})
539 output.append('\n\t{flag} = ({flag} & ~{mask}U) | ((0x6996 >> {parity}) << {bit} & {mask}U);'.format(
540 flag=reg, mask = 1 << bit, bit = bit, parity = parityDst
541 ))
542 else:
543 reg = prog.resolveParam(parity, None, {})
544 output.append('\n\t{flag} = 0x9669 >> {parity} & 1;'.format(flag=reg, parity=parityDst))
545
343 #TODO: combine explicit flags targeting the same storage location 546 #TODO: combine explicit flags targeting the same storage location
344 for flag in explicit: 547 for flag in explicit:
345 location = prog.flags.getStorage(flag) 548 location = prog.flags.getStorage(flag)
346 if type(location) is tuple: 549 if type(location) is tuple:
347 reg,bit = location 550 reg,bit = location
356 else: 559 else:
357 reg = prog.resolveReg(location, None, {}) 560 reg = prog.resolveReg(location, None, {})
358 output.append('\n\t{reg} = {val};'.format(reg=reg, val=explicit[flag])) 561 output.append('\n\t{reg} = {val};'.format(reg=reg, val=explicit[flag]))
359 return ''.join(output) 562 return ''.join(output)
360 563
361 def _cmpCImpl(prog, params): 564 def _cmpCImpl(prog, params, rawParams, flagUpdates):
362 size = prog.paramSize(params[1]) 565 size = prog.paramSize(rawParams[1])
566 needsCarry = False
567 if flagUpdates:
568 for flag in flagUpdates:
569 calc = prog.flags.flagCalc[flag]
570 if calc == 'carry':
571 needsCarry = True
572 break
573 if needsCarry:
574 size *= 2
363 tmpvar = 'cmp_tmp{sz}__'.format(sz=size) 575 tmpvar = 'cmp_tmp{sz}__'.format(sz=size)
364 typename = '' 576 if flagUpdates:
577 prog.carryFlowDst = tmpvar
578 prog.lastA = params[1]
579 prog.lastB = params[0]
580 prog.lastBFlow = params[0]
365 scope = prog.getRootScope() 581 scope = prog.getRootScope()
366 if not scope.resolveLocal(tmpvar): 582 if not scope.resolveLocal(tmpvar):
367 scope.addLocal(tmpvar, size) 583 scope.addLocal(tmpvar, size)
368 prog.lastDst = tmpvar 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
369 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])
370 597
371 def _asrCImpl(prog, params, rawParams): 598 def _asrCImpl(prog, params, rawParams, flagUpdates):
372 shiftSize = prog.paramSize(rawParams[0]) 599 needsCarry = False
373 mask = 1 << (shiftSize - 1) 600 if flagUpdates:
374 return '\n\t{dst} = ({a} >> {b}) | ({a} & {mask});'.format(a = params[0], b = params[1], dst = params[2], mask = mask) 601 for flag in flagUpdates:
375 602 calc = prog.flags.flagCalc[flag]
603 if calc == 'carry':
604 needsCarry = True
605 decl = ''
606 size = prog.paramSize(rawParams[2])
607 if needsCarry:
608 decl,name = prog.getTemp(size * 2)
609 dst = prog.carryFlowDst = name
610 prog.lastA = params[0]
611 else:
612 dst = params[2]
613 mask = 1 << (size - 1)
614 return decl + '\n\t{dst} = ({a} >> {b}) | ({a} & {mask} ? 0xFFFFFFFFU << ({size} - {b}) : 0);'.format(
615 a = params[0], b = params[1], dst = dst, mask = mask, size=size)
616
617 def _sext(size, src):
618 if size == 16:
619 return src | 0xFF00 if src & 0x80 else src & 0x7F
620 else:
621 return src | 0xFFFF0000 if src & 0x8000 else src & 0x7FFF
622
623 def _sextCImpl(prog, params, rawParms):
624 if params[0] == 16:
625 fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src} & 0x7F;'
626 else:
627 fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src} & 0x7FFF;'
628 return fmt.format(src=params[1], dst=params[2])
629
630 def _getCarryCheck(prog):
631 carryFlag = None
632 for flag in prog.flags.flagOrder:
633 if prog.flags.flagCalc[flag] == 'carry':
634 carryFlag = flag
635 break
636 if carryFlag is None:
637 raise Exception('adc requires a defined carry flag')
638 carryStorage = prog.flags.getStorage(carryFlag)
639 if type(carryStorage) is tuple:
640 reg,bit = carryStorage
641 reg = prog.resolveReg(reg, None, (), False)
642 return '({reg} & 1 << {bit})'.format(reg=reg, bit=bit)
643 else:
644 return prog.resolveReg(carryStorage, None, (), False)
645
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
661 needsCarry = needsOflow = needsHalf = False
662 if flagUpdates:
663 for flag in flagUpdates:
664 calc = prog.flags.flagCalc[flag]
665 if calc == 'carry':
666 needsCarry = True
667 elif calc == 'half-carry':
668 needsHalf = True
669 elif calc == 'overflow':
670 needsOflow = True
671 decl = ''
672 carryCheck = _getCarryCheck(prog)
673 vals = '1 : 0'
674 if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust):
675 if len(params) <= 3:
676 size = prog.paramSize(rawParams[2])
677 if needsCarry:
678 size *= 2
679 decl,name = prog.getTemp(size)
680 dst = prog.carryFlowDst = name
681 prog.lastA = params[0]
682 prog.lastB = 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 )
694 else:
695 dst = params[2]
696 return decl + '\n\t{dst} = {a} + {b} + ({check} ? {vals});'.format(dst = dst,
697 a = params[0], b = params[1], check = carryCheck, vals = vals
698 )
699
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
715 needsCarry = needsOflow = needsHalf = False
716 if flagUpdates:
717 for flag in flagUpdates:
718 calc = prog.flags.flagCalc[flag]
719 if calc == 'carry':
720 needsCarry = True
721 elif calc == 'half-carry':
722 needsHalf = True
723 elif calc == 'overflow':
724 needsOflow = True
725 decl = ''
726 carryCheck = _getCarryCheck(prog)
727 vals = '1 : 0'
728 if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust):
729 size = prog.paramSize(rawParams[2])
730 if needsCarry:
731 size *= 2
732 decl,name = prog.getTemp(size)
733 dst = prog.carryFlowDst = name
734 prog.lastA = params[1]
735 prog.lastB = 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 )
747 else:
748 dst = params[2]
749 return decl + '\n\t{dst} = {b} - {a} - ({check} ? {vals});'.format(dst = dst,
750 a = params[0], b = params[1], check=_getCarryCheck(prog), vals = vals
751 )
752
753 def _rolCImpl(prog, params, rawParams, flagUpdates):
754 needsCarry = False
755 if flagUpdates:
756 for flag in flagUpdates:
757 calc = prog.flags.flagCalc[flag]
758 if calc == 'carry':
759 needsCarry = True
760 decl = ''
761 size = prog.paramSize(rawParams[2])
762 if needsCarry:
763 decl,name = prog.getTemp(size * 2)
764 dst = prog.carryFlowDst = name
765 else:
766 dst = params[2]
767 return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} - {b});'.format(dst = dst,
768 a = params[0], b = params[1], size=size
769 )
770
771 def _rlcCImpl(prog, params, rawParams, flagUpdates):
772 needsCarry = False
773 if flagUpdates:
774 for flag in flagUpdates:
775 calc = prog.flags.flagCalc[flag]
776 if calc == 'carry':
777 needsCarry = True
778 decl = ''
779 carryCheck = _getCarryCheck(prog)
780 size = prog.paramSize(rawParams[2])
781 if needsCarry:
782 decl,name = prog.getTemp(size * 2)
783 dst = prog.carryFlowDst = name
784 else:
785 dst = params[2]
786 return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({b} - 1);'.format(dst = dst,
787 a = params[0], b = params[1], size=size, check=carryCheck
788 )
789
790 def _rorCImpl(prog, params, rawParams, flagUpdates):
791 size = prog.paramSize(rawParams[2])
792 return '\n\t{dst} = {a} >> {b} | {a} << ({size} - {b});'.format(dst = params[2],
793 a = params[0], b = params[1], size=size
794 )
795
796 def _rrcCImpl(prog, params, rawParams, flagUpdates):
797 needsCarry = False
798 if flagUpdates:
799 for flag in flagUpdates:
800 calc = prog.flags.flagCalc[flag]
801 if calc == 'carry':
802 needsCarry = True
803 decl = ''
804 carryCheck = _getCarryCheck(prog)
805 size = prog.paramSize(rawParams[2])
806 if needsCarry:
807 decl,name = prog.getTemp(size * 2)
808 dst = prog.carryFlowDst = name
809 else:
810 dst = params[2]
811 return decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({size}-{b});'.format(dst = dst,
812 a = params[0], b = params[1], size=size, check=carryCheck
813 )
814
815 def _updateSyncCImpl(prog, params):
816 return '\n\t{sync}(context, target_cycle);'.format(sync=prog.sync_cycle)
817
376 _opMap = { 818 _opMap = {
377 'mov': Op(lambda val: val).cUnaryOperator(''), 819 'mov': Op(lambda val: val).cUnaryOperator(''),
378 'not': Op(lambda val: ~val).cUnaryOperator('~'), 820 'not': Op(lambda val: ~val).cUnaryOperator('~'),
379 'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'), 821 'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'),
380 'neg': Op(lambda val: -val).cUnaryOperator('-'), 822 'neg': Op(lambda val: -val).cUnaryOperator('-'),
381 'add': Op(lambda a, b: a + b).cBinaryOperator('+'), 823 'add': Op(lambda a, b: a + b).cBinaryOperator('+'),
824 'adc': Op().addImplementation('c', 2, _adcCImpl),
382 'sub': Op(lambda a, b: b - a).cBinaryOperator('-'), 825 'sub': Op(lambda a, b: b - a).cBinaryOperator('-'),
826 'sbc': Op().addImplementation('c', 2, _sbcCImpl),
383 'lsl': Op(lambda a, b: a << b).cBinaryOperator('<<'), 827 'lsl': Op(lambda a, b: a << b).cBinaryOperator('<<'),
384 'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'), 828 'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'),
385 'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl), 829 'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl),
830 'rol': Op().addImplementation('c', 2, _rolCImpl),
831 'rlc': Op().addImplementation('c', 2, _rlcCImpl),
832 'ror': Op().addImplementation('c', 2, _rorCImpl),
833 'rrc': Op().addImplementation('c', 2, _rrcCImpl),
386 'and': Op(lambda a, b: a & b).cBinaryOperator('&'), 834 'and': Op(lambda a, b: a & b).cBinaryOperator('&'),
387 'or': Op(lambda a, b: a | b).cBinaryOperator('|'), 835 'or': Op(lambda a, b: a | b).cBinaryOperator('|'),
388 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'), 836 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'),
389 'abs': Op(lambda val: abs(val)).addImplementation( 837 '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]) 838 'c', 1, lambda prog, params: '\n\t{dst} = abs({src});'.format(dst=params[1], src=params[0])
391 ), 839 ),
392 'cmp': Op().addImplementation('c', None, _cmpCImpl), 840 'cmp': Op().addImplementation('c', None, _cmpCImpl),
841 'sext': Op(_sext).addImplementation('c', 2, _sextCImpl),
393 '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(
394 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:]])
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:]])
395 )), 847 )),
396 'cycles': Op().addImplementation('c', None, 848 'cycles': Op().addImplementation('c', None,
397 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(
398 params[0] 850 params[0]
399 ) 851 )
400 ), 852 ),
401 'addsize': Op( 853 'addsize': Op(
402 lambda a, b: b + (2 * a if a else 1) 854 lambda a, b: b + (2 * a if a else 1)
403 ).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(
404 dst = params[2], sz = params[0], val = params[1] 856 dst = params[2], sz = params[0], val = params[1]
405 )), 857 )),
406 'decsize': Op( 858 'decsize': Op(
407 lambda a, b: b - (2 * a if a else 1) 859 lambda a, b: b - (2 * a if a else 1)
408 ).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(
409 dst = params[2], sz = params[0], val = params[1] 861 dst = params[2], sz = params[0], val = params[1]
410 )), 862 )),
411 'xchg': Op().addImplementation('c', (0,1), _xchgCImpl), 863 'xchg': Op().addImplementation('c', (0,1), _xchgCImpl),
412 'dispatch': Op().addImplementation('c', None, _dispatchCImpl), 864 'dispatch': Op().addImplementation('c', None, _dispatchCImpl),
413 'update_flags': Op().addImplementation('c', None, _updateFlagsCImpl) 865 'update_flags': Op().addImplementation('c', None, _updateFlagsCImpl),
866 'update_sync': Op().addImplementation('c', None, _updateSyncCImpl)
414 } 867 }
415 868
416 #represents a simple DSL instruction 869 #represents a simple DSL instruction
417 class NormalOp: 870 class NormalOp:
418 def __init__(self, parts): 871 def __init__(self, parts):
419 self.op = parts[0] 872 self.op = parts[0]
420 self.params = parts[1:] 873 self.params = parts[1:]
421 874
422 def generate(self, prog, parent, fieldVals, output, otype): 875 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
423 procParams = [] 876 procParams = []
424 allParamsConst = True 877 allParamsConst = flagUpdates is None and not prog.conditional
425 opDef = _opMap.get(self.op) 878 opDef = _opMap.get(self.op)
426 for param in self.params: 879 for param in self.params:
427 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 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
882 if isDst and self.op == 'xchg':
883 #xchg uses its regs as both source and destination
884 #we need to resolve as both so that disperse/coalesce flag stuff gets done
885 prog.resolveParam(param, parent, fieldVals, allowConst, False)
429 param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst) 886 param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst)
430 887
431 if (not type(param) is int) and len(procParams) != len(self.params) - 1: 888 if (not type(param) is int) and len(procParams) != len(self.params) - 1:
432 allParamsConst = False 889 allParamsConst = False
433 procParams.append(param) 890 procParams.append(param)
440 index = str(fieldVals[index]) 897 index = str(fieldVals[index])
441 param = param + '.' + index 898 param = param + '.' + index
442 else: 899 else:
443 param = parent.resolveLocal(param) or param 900 param = parent.resolveLocal(param) or param
444 if param in fieldVals: 901 if param in fieldVals:
445 param = fieldVals[index] 902 param = fieldVals[param]
446 prog.meta[self.params[0]] = param 903 prog.meta[self.params[0]] = param
447 elif self.op == 'dis': 904 elif self.op == 'dis':
448 #TODO: Disassembler 905 #TODO: Disassembler
449 pass 906 pass
450 elif not opDef is None: 907 elif not opDef is None:
908 if opDef.numParams() > len(procParams):
909 raise Exception('Insufficient params for ' + self.op + ' (' + ', '.join(self.params) + ')')
451 if opDef.canEval() and allParamsConst: 910 if opDef.canEval() and allParamsConst:
452 #do constant folding 911 #do constant folding
453 if opDef.numArgs() >= len(procParams): 912 if opDef.numArgs() >= len(procParams):
454 raise Exception('Insufficient args for ' + self.op + ' (' + ', '.join(self.params) + ')') 913 raise Exception('Insufficient args for ' + self.op + ' (' + ', '.join(self.params) + ')')
455 dst = self.params[opDef.numArgs()] 914 dst = self.params[opDef.numArgs()]
459 maybeLocal = parent.resolveLocal(dst) 918 maybeLocal = parent.resolveLocal(dst)
460 if maybeLocal: 919 if maybeLocal:
461 dst = maybeLocal 920 dst = maybeLocal
462 parent.regValues[dst] = result 921 parent.regValues[dst] = result
463 if prog.isReg(dst): 922 if prog.isReg(dst):
464 output.append(_opMap['mov'].generate(otype, prog, procParams, self.params)) 923 shortProc = (procParams[0], procParams[-1])
465 else: 924 shortParams = (self.params[0], self.params[-1])
466 output.append(opDef.generate(otype, prog, procParams, self.params)) 925 output.append(_opMap['mov'].generate(otype, prog, shortProc, shortParams, None))
926 else:
927 output.append(opDef.generate(otype, prog, procParams, self.params, flagUpdates))
928 for dstIdx in opDef.outOp:
929 dst = self.params[dstIdx]
930 while dst in prog.meta:
931 dst = prog.meta[dst]
932 if dst in parent.regValues:
933 del parent.regValues[dst]
934
467 elif self.op in prog.subroutines: 935 elif self.op in prog.subroutines:
936 procParams = []
937 for param in self.params:
938 begin,sep,end = param.partition('.')
939 if sep:
940 if end in fieldVals:
941 param = begin + '.' + str(fieldVals[end])
942 else:
943 if param in fieldVals:
944 param = fieldVals[param]
945 else:
946 maybeLocal = parent.resolveLocal(param)
947 if maybeLocal and maybeLocal in parent.regValues:
948 param = parent.regValues[maybeLocal]
949 procParams.append(param)
468 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent) 950 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent)
469 else: 951 else:
470 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]) + ');')
471 prog.lastOp = self 953 prog.lastOp = self
472 954
515 def localSize(self, name): 997 def localSize(self, name):
516 if name in self.current_locals: 998 if name in self.current_locals:
517 return self.current_locals[name] 999 return self.current_locals[name]
518 return self.parent.localSize(name) 1000 return self.parent.localSize(name)
519 1001
520 def generate(self, prog, parent, fieldVals, output, otype): 1002 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
521 prog.pushScope(self) 1003 prog.pushScope(self)
522 param = prog.resolveParam(self.param, parent, fieldVals) 1004 param = prog.resolveParam(self.param, parent, fieldVals)
523 if type(param) is int: 1005 if type(param) is int:
524 self.regValues = self.parent.regValues 1006 self.regValues = self.parent.regValues
525 if param in self.cases: 1007 if param in self.cases:
526 self.current_locals = self.case_locals[param] 1008 self.current_locals = self.case_locals[param]
527 output.append('\n\t{') 1009 output.append('\n\t{')
528 for local in self.case_locals[param]: 1010 for local in self.case_locals[param]:
529 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local)) 1011 output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local))
530 for op in self.cases[param]: 1012 self.processOps(prog, fieldVals, output, otype, self.cases[param])
531 op.generate(prog, self, fieldVals, output, otype)
532 output.append('\n\t}') 1013 output.append('\n\t}')
533 elif self.default: 1014 elif self.default:
534 self.current_locals = self.default_locals 1015 self.current_locals = self.default_locals
535 output.append('\n\t{') 1016 output.append('\n\t{')
536 for local in self.default_locals: 1017 for local in self.default_locals:
537 output.append('\n\tuint{0}_t {1};'.format(self.default[local], local)) 1018 output.append('\n\tuint{0}_t {1};'.format(self.default[local], local))
538 for op in self.default: 1019 self.processOps(prog, fieldVals, output, otype, self.default)
539 op.generate(prog, self, fieldVals, output, otype)
540 output.append('\n\t}') 1020 output.append('\n\t}')
541 else: 1021 else:
1022 oldCond = prog.conditional
1023 prog.conditional = True
542 output.append('\n\tswitch(' + param + ')') 1024 output.append('\n\tswitch(' + param + ')')
543 output.append('\n\t{') 1025 output.append('\n\t{')
544 for case in self.cases: 1026 for case in self.cases:
1027 #temp = prog.temp.copy()
545 self.current_locals = self.case_locals[case] 1028 self.current_locals = self.case_locals[case]
546 self.regValues = dict(self.parent.regValues) 1029 self.regValues = dict(self.parent.regValues)
547 output.append('\n\tcase {0}U: '.format(case) + '{') 1030 output.append('\n\tcase {0}U: '.format(case) + '{')
548 for local in self.case_locals[case]: 1031 for local in self.case_locals[case]:
549 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))
550 for op in self.cases[case]: 1033 self.processOps(prog, fieldVals, output, otype, self.cases[case])
551 op.generate(prog, self, fieldVals, output, otype)
552 output.append('\n\tbreak;') 1034 output.append('\n\tbreak;')
553 output.append('\n\t}') 1035 output.append('\n\t}')
1036 #prog.temp = temp
554 if self.default: 1037 if self.default:
1038 #temp = prog.temp.copy()
555 self.current_locals = self.default_locals 1039 self.current_locals = self.default_locals
556 self.regValues = dict(self.parent.regValues) 1040 self.regValues = dict(self.parent.regValues)
557 output.append('\n\tdefault: {') 1041 output.append('\n\tdefault: {')
558 for local in self.default_locals: 1042 for local in self.default_locals:
559 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))
560 for op in self.default: 1044 self.processOps(prog, fieldVals, output, otype, self.default)
561 op.generate(prog, self, fieldVals, output, otype) 1045 #prog.temp = temp
562 output.append('\n\t}') 1046 output.append('\n\t}')
1047 prog.conditional = oldCond
563 prog.popScope() 1048 prog.popScope()
564 1049
565 def __str__(self): 1050 def __str__(self):
566 keys = self.cases.keys() 1051 keys = self.cases.keys()
567 keys.sort() 1052 keys.sort()
577 if prog.lastOp.op == 'cmp': 1062 if prog.lastOp.op == 'cmp':
578 output.pop() 1063 output.pop()
579 params = [prog.resolveParam(p, parent, fieldVals) for p in prog.lastOp.params] 1064 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]) + '{' 1065 return '\n\tif ({a} >= {b}) '.format(a=params[1], b = params[0]) + '{'
581 else: 1066 else:
582 raise ion(">=U not implemented in the general case yet") 1067 raise Exception(">=U not implemented in the general case yet")
1068
1069 def _eqCImpl(prog, parent, fieldVals, output):
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, {}))
1076
1077 def _neqCImpl(prog, parent, fieldVals, output):
1078 return '\n\tif ({a}) {{'.format(a=prog.resolveParam(prog.lastDst, None, {}))
583 1079
584 _ifCmpImpl = { 1080 _ifCmpImpl = {
585 'c': { 1081 'c': {
586 '>=U': _geuCImpl 1082 '>=U': _geuCImpl,
1083 '=': _eqCImpl,
1084 '!=': _neqCImpl
587 } 1085 }
588 } 1086 }
589 #represents a DSL conditional construct 1087 #represents a DSL conditional construct
590 class If(ChildBlock): 1088 class If(ChildBlock):
591 def __init__(self, parent, cond): 1089 def __init__(self, parent, cond):
604 if op.op in ('case', 'arg'): 1102 if op.op in ('case', 'arg'):
605 raise Exception(self.op + ' is not allows inside an if block') 1103 raise Exception(self.op + ' is not allows inside an if block')
606 if op.op == 'local': 1104 if op.op == 'local':
607 name = op.params[0] 1105 name = op.params[0]
608 size = op.params[1] 1106 size = op.params[1]
609 self.locals[name] = size 1107 self.curLocals[name] = size
610 elif op.op == 'else': 1108 elif op.op == 'else':
611 self.curLocals = self.elseLocals 1109 self.curLocals = self.elseLocals
612 self.curBody = self.elseBody 1110 self.curBody = self.elseBody
613 else: 1111 else:
614 self.curBody.append(op) 1112 self.curBody.append(op)
615 1113
616 def localSize(self, name): 1114 def localSize(self, name):
617 return self.curLocals.get(name) 1115 return self.curLocals.get(name)
618 1116
619 def resolveLocal(self, name): 1117 def resolveLocal(self, name):
620 if name in self.locals: 1118 if name in self.curLocals:
621 return name 1119 return name
622 return self.parent.resolveLocal(name) 1120 return self.parent.resolveLocal(name)
623 1121
624 def _genTrueBody(self, prog, fieldVals, output, otype): 1122 def _genTrueBody(self, prog, fieldVals, output, otype):
625 self.curLocals = self.locals 1123 self.curLocals = self.locals
1124 subOut = []
1125 self.processOps(prog, fieldVals, subOut, otype, self.body)
626 for local in self.locals: 1126 for local in self.locals:
627 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.locals[local], nm=local)) 1127 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.locals[local], nm=local))
628 for op in self.body: 1128 output += subOut
629 op.generate(prog, self, fieldVals, output, otype)
630 1129
631 def _genFalseBody(self, prog, fieldVals, output, otype): 1130 def _genFalseBody(self, prog, fieldVals, output, otype):
632 self.curLocals = self.elseLocals 1131 self.curLocals = self.elseLocals
1132 subOut = []
1133 self.processOps(prog, fieldVals, subOut, otype, self.elseBody)
633 for local in self.elseLocals: 1134 for local in self.elseLocals:
634 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.elseLocals[local], nm=local)) 1135 output.append('\n\tuint{sz}_t {nm};'.format(sz=self.elseLocals[local], nm=local))
635 for op in self.elseBody: 1136 output += subOut
636 op.generate(prog, self, fieldVals, output, otype)
637 1137
638 def _genConstParam(self, param, prog, fieldVals, output, otype): 1138 def _genConstParam(self, param, prog, fieldVals, output, otype):
639 if param: 1139 if param:
640 self._genTrueBody(prog, fieldVals, output, otype) 1140 self._genTrueBody(prog, fieldVals, output, otype)
641 else: 1141 else:
642 self._genFalseBody(prog, fieldVals, output, otype) 1142 self._genFalseBody(prog, fieldVals, output, otype)
643 1143
644 def generate(self, prog, parent, fieldVals, output, otype): 1144 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
645 self.regValues = parent.regValues 1145 self.regValues = parent.regValues
646 try: 1146 if self.cond in prog.booleans:
647 self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype) 1147 self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype)
648 except Exception: 1148 else:
649 if self.cond in _ifCmpImpl[otype]: 1149 if self.cond in _ifCmpImpl[otype]:
1150 oldCond = prog.conditional
1151 prog.conditional = True
1152 #temp = prog.temp.copy()
650 output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output)) 1153 output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output))
651 self._genTrueBody(prog, fieldVals, output, otype) 1154 self._genTrueBody(prog, fieldVals, output, otype)
1155 #prog.temp = temp
652 if self.elseBody: 1156 if self.elseBody:
1157 #temp = prog.temp.copy()
653 output.append('\n\t} else {') 1158 output.append('\n\t} else {')
654 self._genFalseBody(prog, fieldVals, output, otype) 1159 self._genFalseBody(prog, fieldVals, output, otype)
1160 #prog.temp = temp
655 output.append('\n\t}') 1161 output.append('\n\t}')
1162 prog.conditional = oldCond
656 else: 1163 else:
657 cond = prog.resolveParam(self.cond, parent, fieldVals) 1164 cond = prog.resolveParam(self.cond, parent, fieldVals)
658 if type(cond) is int: 1165 if type(cond) is int:
659 self._genConstParam(cond, prog, fieldVals, output, otype) 1166 self._genConstParam(cond, prog, fieldVals, output, otype)
660 else: 1167 else:
1168 #temp = prog.temp.copy()
661 output.append('\n\tif ({cond}) '.format(cond=cond) + '{') 1169 output.append('\n\tif ({cond}) '.format(cond=cond) + '{')
1170 oldCond = prog.conditional
1171 prog.conditional = True
662 self._genTrueBody(prog, fieldVals, output, otype) 1172 self._genTrueBody(prog, fieldVals, output, otype)
1173 #prog.temp = temp
663 if self.elseBody: 1174 if self.elseBody:
1175 #temp = prog.temp.copy()
664 output.append('\n\t} else {') 1176 output.append('\n\t} else {')
665 self._genFalseBody(prog, fieldVals, output, otype) 1177 self._genFalseBody(prog, fieldVals, output, otype)
1178 #prog.temp = temp
666 output.append('\n\t}') 1179 output.append('\n\t}')
1180 prog.conditional = oldCond
667 1181
668 1182
669 def __str__(self): 1183 def __str__(self):
670 lines = ['\n\tif'] 1184 lines = ['\n\tif']
671 for op in self.body: 1185 for op in self.body:
677 def __init__(self): 1191 def __init__(self):
678 self.regs = {} 1192 self.regs = {}
679 self.pointers = {} 1193 self.pointers = {}
680 self.regArrays = {} 1194 self.regArrays = {}
681 self.regToArray = {} 1195 self.regToArray = {}
1196 self.addReg('cycles', 32)
1197 self.addReg('sync_cycle', 32)
682 1198
683 def addReg(self, name, size): 1199 def addReg(self, name, size):
684 self.regs[name] = size 1200 self.regs[name] = size
685 1201
686 def addPointer(self, name, size): 1202 def addPointer(self, name, size, count):
687 self.pointers[name] = size 1203 self.pointers[name] = (size, count)
688 1204
689 def addRegArray(self, name, size, regs): 1205 def addRegArray(self, name, size, regs):
690 self.regArrays[name] = (size, regs) 1206 self.regArrays[name] = (size, regs)
691 idx = 0 1207 idx = 0
692 if not type(regs) is int: 1208 if not type(regs) is int:
719 def isNamedArray(self, array): 1235 def isNamedArray(self, array):
720 return array in self.regArrays and type(self.regArrays[array][1]) is int 1236 return array in self.regArrays and type(self.regArrays[array][1]) is int
721 1237
722 def processLine(self, parts): 1238 def processLine(self, parts):
723 if len(parts) == 3: 1239 if len(parts) == 3:
724 self.addRegArray(parts[0], int(parts[1]), int(parts[2])) 1240 if parts[1].startswith('ptr'):
1241 self.addPointer(parts[0], parts[1][3:], int(parts[2]))
1242 else:
1243 self.addRegArray(parts[0], int(parts[1]), int(parts[2]))
725 elif len(parts) > 2: 1244 elif len(parts) > 2:
726 self.addRegArray(parts[0], int(parts[1]), parts[2:]) 1245 self.addRegArray(parts[0], int(parts[1]), parts[2:])
727 else: 1246 else:
728 if parts[1].startswith('ptr'): 1247 if parts[1].startswith('ptr'):
729 self.addPointer(parts[0], int(parts[1][3:])) 1248 self.addPointer(parts[0], parts[1][3:], 1)
730 else: 1249 else:
731 self.addReg(parts[0], int(parts[1])) 1250 self.addReg(parts[0], int(parts[1]))
732 return self 1251 return self
733 1252
734 def writeHeader(self, otype, hFile): 1253 def writeHeader(self, otype, hFile):
735 fieldList = [] 1254 fieldList = []
736 for pointer in self.pointers: 1255 for pointer in self.pointers:
737 hFile.write('\n\tuint{sz}_t *{nm};'.format(nm=pointer, sz=self.pointers[pointer])) 1256 stars = '*'
1257 ptype, count = self.pointers[pointer]
1258 while ptype.startswith('ptr'):
1259 stars += '*'
1260 ptype = ptype[3:]
1261 if ptype.isdigit():
1262 ptype = 'uint{sz}_t'.format(sz=ptype)
1263 if count > 1:
1264 arr = '[{n}]'.format(n=count)
1265 else:
1266 arr = ''
1267 hFile.write('\n\t{ptype} {stars}{nm}{arr};'.format(nm=pointer, ptype=ptype, stars=stars, arr=arr))
738 for reg in self.regs: 1268 for reg in self.regs:
739 if not self.isRegArrayMember(reg): 1269 if not self.isRegArrayMember(reg):
740 fieldList.append((self.regs[reg], 1, reg)) 1270 fieldList.append((self.regs[reg], 1, reg))
741 for arr in self.regArrays: 1271 for arr in self.regArrays:
742 size,regs = self.regArrays[arr] 1272 size,regs = self.regArrays[arr]
754 class Flags: 1284 class Flags:
755 def __init__(self): 1285 def __init__(self):
756 self.flagBits = {} 1286 self.flagBits = {}
757 self.flagCalc = {} 1287 self.flagCalc = {}
758 self.flagStorage = {} 1288 self.flagStorage = {}
1289 self.flagOrder = []
759 self.flagReg = None 1290 self.flagReg = None
1291 self.storageToFlags = {}
760 self.maxBit = -1 1292 self.maxBit = -1
761 1293
762 def processLine(self, parts): 1294 def processLine(self, parts):
763 if parts[0] == 'register': 1295 if parts[0] == 'register':
764 self.flagReg = parts[1] 1296 self.flagReg = parts[1]
775 if bit > self.maxBit: 1307 if bit > self.maxBit:
776 self.maxBit = bit 1308 self.maxBit = bit
777 self.flagBits[flag] = bit 1309 self.flagBits[flag] = bit
778 self.flagCalc[flag] = calc 1310 self.flagCalc[flag] = calc
779 self.flagStorage[flag] = storage 1311 self.flagStorage[flag] = storage
1312 storage,_,storebit = storage.partition('.')
1313 self.storageToFlags.setdefault(storage, []).append((storebit, flag))
1314 self.flagOrder.append(flag)
780 return self 1315 return self
781 1316
782 def getStorage(self, flag): 1317 def getStorage(self, flag):
783 if not flag in self.flagStorage: 1318 if not flag in self.flagStorage:
784 raise Exception('Undefined flag ' + flag) 1319 raise Exception('Undefined flag ' + flag)
785 loc,_,bit = self.flagStorage[flag].partition('.') 1320 loc,_,bit = self.flagStorage[flag].partition('.')
786 if bit: 1321 if bit:
787 return (loc, int(bit)) 1322 return (loc, int(bit))
788 else: 1323 else:
789 return loc 1324 return loc
1325
1326 def parseFlagUpdate(self, flagString):
1327 last = ''
1328 autoUpdate = set()
1329 explicit = {}
1330 for c in flagString:
1331 if c.isdigit():
1332 if last.isalpha():
1333 num = int(c)
1334 if num > 1:
1335 raise Exception(c + ' is not a valid digit for update_flags')
1336 explicit[last] = num
1337 last = c
1338 else:
1339 raise Exception('Digit must follow flag letter in update_flags')
1340 else:
1341 if last.isalpha():
1342 autoUpdate.add(last)
1343 last = c
1344 if last.isalpha():
1345 autoUpdate.add(last)
1346 return (autoUpdate, explicit)
790 1347
791 def disperseFlags(self, prog, otype): 1348 def disperseFlags(self, prog, otype):
792 bitToFlag = [None] * (self.maxBit+1) 1349 bitToFlag = [None] * (self.maxBit+1)
793 src = prog.resolveReg(self.flagReg, None, {}) 1350 src = prog.resolveReg(self.flagReg, None, {})
794 output = [] 1351 output = []
882 else: 1439 else:
883 output.append('\n\tif ({src} & (1 << {srcbit})) {{\n\t\t{dst} |= 1 << {dstbit};\n\t}}'.format( 1440 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 1441 src=src, dst=dst, srcbit=srcbit, dstbit=dstbit
885 )) 1442 ))
886 if direct: 1443 if direct:
887 output.append('\n\t{dst} |= {src} & {mask}'.format( 1444 output.append('\n\t{dst} |= {src} & {mask};'.format(
888 dst=dst, src=src, mask=direct 1445 dst=dst, src=src, mask=direct
889 )) 1446 ))
890 return ''.join(output) 1447 return ''.join(output)
891 1448
892 1449
900 self.prefix = info.get('prefix', [''])[0] 1457 self.prefix = info.get('prefix', [''])[0]
901 self.opsize = int(info.get('opcode_size', ['8'])[0]) 1458 self.opsize = int(info.get('opcode_size', ['8'])[0])
902 self.extra_tables = info.get('extra_tables', []) 1459 self.extra_tables = info.get('extra_tables', [])
903 self.context_type = self.prefix + 'context' 1460 self.context_type = self.prefix + 'context'
904 self.body = info.get('body', [None])[0] 1461 self.body = info.get('body', [None])[0]
1462 self.interrupt = info.get('interrupt', [None])[0]
1463 self.sync_cycle = info.get('sync_cycle', [None])[0]
905 self.includes = info.get('include', []) 1464 self.includes = info.get('include', [])
906 self.flags = flags 1465 self.flags = flags
907 self.lastDst = None 1466 self.lastDst = None
908 self.scopes = [] 1467 self.scopes = []
909 self.currentScope = None 1468 self.currentScope = None
910 self.lastOp = None 1469 self.lastOp = None
1470 self.carryFlowDst = None
1471 self.lastA = None
1472 self.lastB = None
1473 self.lastBFlow = None
1474 self.sizeAdjust = None
1475 self.conditional = False
1476 self.declares = []
1477 self.lastSize = None
911 1478
912 def __str__(self): 1479 def __str__(self):
913 pieces = [] 1480 pieces = []
914 for reg in self.regs: 1481 for reg in self.regs:
915 pieces.append(str(self.regs[reg])) 1482 pieces.append(str(self.regs[reg]))
928 hFile.write('\n\ntypedef struct {') 1495 hFile.write('\n\ntypedef struct {')
929 hFile.write('\n\tcpu_options gen;') 1496 hFile.write('\n\tcpu_options gen;')
930 hFile.write('\n}} {0}options;'.format(self.prefix)) 1497 hFile.write('\n}} {0}options;'.format(self.prefix))
931 hFile.write('\n\ntypedef struct {') 1498 hFile.write('\n\ntypedef struct {')
932 hFile.write('\n\t{0}options *opts;'.format(self.prefix)) 1499 hFile.write('\n\t{0}options *opts;'.format(self.prefix))
933 hFile.write('\n\tuint32_t cycles;')
934 self.regs.writeHeader(otype, hFile) 1500 self.regs.writeHeader(otype, hFile)
935 hFile.write('\n}} {0}context;'.format(self.prefix)) 1501 hFile.write('\n}} {0}context;'.format(self.prefix))
936 hFile.write('\n') 1502 hFile.write('\n')
1503 hFile.write('\nvoid {pre}execute({type} *context, uint32_t target_cycle);'.format(pre = self.prefix, type = self.context_type))
1504 for decl in self.declares:
1505 hFile.write('\n' + decl)
937 hFile.write('\n#endif //{0}_'.format(macro)) 1506 hFile.write('\n#endif //{0}_'.format(macro))
938 hFile.write('\n') 1507 hFile.write('\n')
939 hFile.close() 1508 hFile.close()
940 def build(self, otype): 1509
941 body = [] 1510 def _buildTable(self, otype, table, body, lateBody):
942 pieces = [] 1511 pieces = []
943 for include in self.includes: 1512 opmap = [None] * (1 << self.opsize)
944 body.append('#include "{0}"\n'.format(include)) 1513 bodymap = {}
945 for table in self.instructions: 1514 if table in self.instructions:
946 opmap = [None] * (1 << self.opsize)
947 bodymap = {}
948 instructions = self.instructions[table] 1515 instructions = self.instructions[table]
949 instructions.sort() 1516 instructions.sort()
950 for inst in instructions: 1517 for inst in instructions:
951 for val in inst.allValues(): 1518 for val in inst.allValues():
952 if opmap[val] is None: 1519 if opmap[val] is None:
955 self.needFlagCoalesce = False 1522 self.needFlagCoalesce = False
956 self.needFlagDisperse = False 1523 self.needFlagDisperse = False
957 self.lastOp = None 1524 self.lastOp = None
958 opmap[val] = inst.generateName(val) 1525 opmap[val] = inst.generateName(val)
959 bodymap[val] = inst.generateBody(val, self, otype) 1526 bodymap[val] = inst.generateBody(val, self, otype)
960 1527
961 pieces.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix)) 1528 if self.dispatch == 'call':
962 pieces.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap))) 1529 pieces.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
963 for inst in range(0, len(opmap)): 1530 for inst in range(0, len(opmap)):
964 op = opmap[inst] 1531 op = opmap[inst]
965 if op is None: 1532 if op is None:
966 pieces.append('\n\tunimplemented,') 1533 pieces.append('\n\tunimplemented,')
967 else: 1534 else:
968 pieces.append('\n\t' + op + ',') 1535 pieces.append('\n\t' + op + ',')
969 body.append(bodymap[inst]) 1536 body.append(bodymap[inst])
970 pieces.append('\n};') 1537 pieces.append('\n};')
971 if self.body in self.subroutines: 1538 elif self.dispatch == 'goto':
1539 body.append('\n\tstatic void *impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
1540 for inst in range(0, len(opmap)):
1541 op = opmap[inst]
1542 if op is None:
1543 body.append('\n\t\t&&unimplemented,')
1544 else:
1545 body.append('\n\t\t&&' + op + ',')
1546 lateBody.append(bodymap[inst])
1547 body.append('\n\t};')
1548 else:
1549 raise Exception("unimplmeneted dispatch type " + self.dispatch)
1550 body.extend(pieces)
1551
1552 def nextInstruction(self, otype):
1553 output = []
1554 if self.dispatch == 'goto':
1555 if self.interrupt in self.subroutines:
1556 output.append('\n\tif (context->cycles >= context->sync_cycle) {')
1557 output.append('\n\tif (context->cycles >= target_cycle) { return; }')
1558 if self.interrupt in self.subroutines:
1559 self.meta = {}
1560 self.temp = {}
1561 self.subroutines[self.interrupt].inline(self, [], output, otype, None)
1562 output.append('\n\t}')
1563
1564 self.meta = {}
1565 self.temp = {}
1566 self.subroutines[self.body].inline(self, [], output, otype, None)
1567 return output
1568
1569 def build(self, otype):
1570 body = []
1571 pieces = []
1572 for include in self.includes:
1573 body.append('#include "{0}"\n'.format(include))
1574 if self.dispatch == 'call':
1575 body.append('\nstatic void unimplemented({pre}context *context, uint32_t target_cycle)'.format(pre = self.prefix))
1576 body.append('\n{')
1577 body.append('\n\tfatal_error("Unimplemented instruction\\n");')
1578 body.append('\n}\n')
1579 body.append('\ntypedef void (*impl_fun)({pre}context *context, uint32_t target_cycle);'.format(pre=self.prefix))
1580 for table in self.extra_tables:
1581 body.append('\nstatic impl_fun impl_{name}[{sz}];'.format(name = table, sz=(1 << self.opsize)))
1582 body.append('\nstatic impl_fun impl_main[{sz}];'.format(sz=(1 << self.opsize)))
1583 elif self.dispatch == 'goto':
1584 body.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type))
1585 body.append('\n{')
1586
1587 for table in self.extra_tables:
1588 self._buildTable(otype, table, body, pieces)
1589 self._buildTable(otype, 'main', body, pieces)
1590 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)) 1591 pieces.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type))
973 pieces.append('\n{') 1592 pieces.append('\n{')
1593 pieces.append('\n\t{sync}(context, target_cycle);'.format(sync=self.sync_cycle))
974 pieces.append('\n\twhile (context->cycles < target_cycle)') 1594 pieces.append('\n\twhile (context->cycles < target_cycle)')
975 pieces.append('\n\t{') 1595 pieces.append('\n\t{')
1596 if self.interrupt in self.subroutines:
1597 pieces.append('\n\t\tif (context->cycles >= context->sync_cycle) {')
1598 self.meta = {}
1599 self.temp = {}
1600 intpieces = []
1601 self.subroutines[self.interrupt].inline(self, [], intpieces, otype, None)
1602 for size in self.temp:
1603 pieces.append('\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size))
1604 pieces += intpieces
1605 pieces.append('\n\t\t}')
976 self.meta = {} 1606 self.meta = {}
977 self.temp = {} 1607 self.temp = {}
978 self.subroutines[self.body].inline(self, [], pieces, otype, None) 1608 self.subroutines[self.body].inline(self, [], pieces, otype, None)
979 pieces.append('\n\t}') 1609 pieces.append('\n\t}')
980 pieces.append('\n}') 1610 pieces.append('\n}')
981 body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix)) 1611 elif self.dispatch == 'goto':
982 body.append('\n{') 1612 body.append('\n\t{sync}(context, target_cycle);'.format(sync=self.sync_cycle))
983 body.append('\n\tfatal_error("Unimplemented instruction");') 1613 body += self.nextInstruction(otype)
984 body.append('\n}\n') 1614 pieces.append('\nunimplemented:')
1615 pieces.append('\n\tfatal_error("Unimplemented instruction\\n");')
1616 pieces.append('\n}')
985 return ''.join(body) + ''.join(pieces) 1617 return ''.join(body) + ''.join(pieces)
986 1618
987 def checkBool(self, name): 1619 def checkBool(self, name):
988 if not name in self.booleans: 1620 if not name in self.booleans:
989 raise Exception(name + ' is not a defined boolean flag') 1621 raise Exception(name + ' is not a defined boolean flag')
990 return self.booleans[name] 1622 return self.booleans[name]
991 1623
992 def getTemp(self, size): 1624 def getTemp(self, size):
993 if size in self.temp: 1625 if size in self.temp:
994 return ('', self.temp[size]) 1626 return ('', self.temp[size])
995 self.temp[size] = 'tmp{sz}'.format(sz=size); 1627 self.temp[size] = 'gen_tmp{sz}__'.format(sz=size);
996 return ('\n\tuint{sz}_t tmp{sz};'.format(sz=size), self.temp[size]) 1628 return ('', self.temp[size])
997 1629
998 def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False): 1630 def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False):
999 keepGoing = True 1631 keepGoing = True
1000 while keepGoing: 1632 while keepGoing:
1001 keepGoing = False 1633 keepGoing = False
1011 if parent: 1643 if parent:
1012 if param in parent.regValues and allowConstant: 1644 if param in parent.regValues and allowConstant:
1013 return parent.regValues[param] 1645 return parent.regValues[param]
1014 maybeLocal = parent.resolveLocal(param) 1646 maybeLocal = parent.resolveLocal(param)
1015 if maybeLocal: 1647 if maybeLocal:
1648 if isdst:
1649 self.lastDst = param
1650 self.lastSize = None
1016 return maybeLocal 1651 return maybeLocal
1017 if param in fieldVals: 1652 if param in fieldVals:
1018 param = fieldVals[param] 1653 param = fieldVals[param]
1654 fieldVals = {}
1655 keepGoing = True
1019 elif param in self.meta: 1656 elif param in self.meta:
1020 param = self.meta[param] 1657 param = self.meta[param]
1021 keepGoing = True 1658 keepGoing = True
1022 elif self.isReg(param): 1659 elif self.isReg(param):
1023 param = self.resolveReg(param, parent, fieldVals, isdst) 1660 return self.resolveReg(param, parent, fieldVals, isdst)
1661 elif param in self.regs.pointers:
1662 return 'context->' + param
1663 if isdst:
1664 self.lastDst = param
1665 self.lastSize = None
1024 return param 1666 return param
1025 1667
1026 def isReg(self, name): 1668 def isReg(self, name):
1027 if not type(name) is str: 1669 if not type(name) is str:
1028 return False 1670 return False
1068 return ret 1710 return ret
1069 1711
1070 1712
1071 1713
1072 def paramSize(self, name): 1714 def paramSize(self, name):
1073 size = self.currentScope.localSize(name) 1715 if name in self.meta:
1074 if size: 1716 return self.paramSize(self.meta[name])
1075 return size 1717 for i in range(len(self.scopes) -1, -1, -1):
1718 size = self.scopes[i].localSize(name)
1719 if size:
1720 return size
1076 begin,sep,_ = name.partition('.') 1721 begin,sep,_ = name.partition('.')
1077 if sep and self.regs.isRegArray(begin): 1722 if sep and self.regs.isRegArray(begin):
1078 return self.regs.regArrays[begin][0] 1723 return self.regs.regArrays[begin][0]
1079 if self.regs.isReg(name): 1724 if self.regs.isReg(name):
1080 return self.regs.regs[name] 1725 return self.regs.regs[name]
1081 return 32 1726 return 32
1082 1727
1728 def getLastSize(self):
1729 if self.lastSize:
1730 return self.lastSize
1731 return self.paramSize(self.lastDst)
1732
1083 def pushScope(self, scope): 1733 def pushScope(self, scope):
1084 self.scopes.append(scope) 1734 self.scopes.append(scope)
1085 self.currentScope = scope 1735 self.currentScope = scope
1086 1736
1087 def popScope(self): 1737 def popScope(self):
1090 return ret 1740 return ret
1091 1741
1092 def getRootScope(self): 1742 def getRootScope(self):
1093 return self.scopes[0] 1743 return self.scopes[0]
1094 1744
1095 def parse(f): 1745 def parse(args):
1746 f = args.source
1096 instructions = {} 1747 instructions = {}
1097 subroutines = {} 1748 subroutines = {}
1098 registers = None 1749 registers = None
1099 flags = None 1750 flags = None
1751 declares = []
1100 errors = [] 1752 errors = []
1101 info = {} 1753 info = {}
1102 line_num = 0 1754 line_num = 0
1103 cur_object = None 1755 cur_object = None
1104 for line in f: 1756 for line in f:
1106 line,_,comment = line.partition('#') 1758 line,_,comment = line.partition('#')
1107 if not line.strip(): 1759 if not line.strip():
1108 continue 1760 continue
1109 if line[0].isspace(): 1761 if line[0].isspace():
1110 if not cur_object is None: 1762 if not cur_object is None:
1111 parts = [el.strip() for el in line.split(' ')] 1763 sep = True
1764 parts = []
1765 while sep:
1766 before,sep,after = line.partition('"')
1767 before = before.strip()
1768 if before:
1769 parts += [el.strip() for el in before.split(' ')]
1770 if sep:
1771 #TODO: deal with escaped quotes
1772 inside,sep,after = after.partition('"')
1773 parts.append('"' + inside + '"')
1774 line = after
1112 if type(cur_object) is dict: 1775 if type(cur_object) is dict:
1113 cur_object[parts[0]] = parts[1:] 1776 cur_object[parts[0]] = parts[1:]
1777 elif type(cur_object) is list:
1778 cur_object.append(' '.join(parts))
1114 else: 1779 else:
1115 cur_object = cur_object.processLine(parts) 1780 cur_object = cur_object.processLine(parts)
1116 1781
1117 # if type(cur_object) is Registers: 1782 # if type(cur_object) is Registers:
1118 # if len(parts) > 2: 1783 # if len(parts) > 2:
1166 cur_object = info 1831 cur_object = info
1167 elif line.strip() == 'flags': 1832 elif line.strip() == 'flags':
1168 if flags is None: 1833 if flags is None:
1169 flags = Flags() 1834 flags = Flags()
1170 cur_object = flags 1835 cur_object = flags
1836 elif line.strip() == 'declare':
1837 cur_object = declares
1171 else: 1838 else:
1172 cur_object = SubRoutine(line.strip()) 1839 cur_object = SubRoutine(line.strip())
1173 subroutines[cur_object.name] = cur_object 1840 subroutines[cur_object.name] = cur_object
1174 if errors: 1841 if errors:
1175 print(errors) 1842 print(errors)
1176 else: 1843 else:
1177 p = Program(registers, instructions, subroutines, info, flags) 1844 p = Program(registers, instructions, subroutines, info, flags)
1845 p.dispatch = args.dispatch
1846 p.declares = declares
1178 p.booleans['dynarec'] = False 1847 p.booleans['dynarec'] = False
1179 p.booleans['interp'] = True 1848 p.booleans['interp'] = True
1849 if args.define:
1850 for define in args.define:
1851 name,sep,val = define.partition('=')
1852 name = name.strip()
1853 val = val.strip()
1854 if sep:
1855 p.booleans[name] = bool(val)
1856 else:
1857 p.booleans[name] = True
1180 1858
1181 if 'header' in info: 1859 if 'header' in info:
1182 print('#include "{0}"'.format(info['header'][0])) 1860 print('#include "{0}"'.format(info['header'][0]))
1183 p.writeHeader('c', info['header'][0]) 1861 p.writeHeader('c', info['header'][0])
1184 print('#include "util.h"') 1862 print('#include "util.h"')
1185 print('#include <stdlib.h>') 1863 print('#include <stdlib.h>')
1186 print(p.build('c')) 1864 print(p.build('c'))
1187 1865
1188 def main(argv): 1866 def main(argv):
1189 f = open(argv[1]) 1867 from argparse import ArgumentParser, FileType
1190 parse(f) 1868 argParser = ArgumentParser(description='CPU emulator DSL compiler')
1869 argParser.add_argument('source', type=FileType('r'))
1870 argParser.add_argument('-D', '--define', action='append')
1871 argParser.add_argument('-d', '--dispatch', choices=('call', 'switch', 'goto'), default='call')
1872 parse(argParser.parse_args(argv[1:]))
1191 1873
1192 if __name__ == '__main__': 1874 if __name__ == '__main__':
1193 from sys import argv 1875 from sys import argv
1194 main(argv) 1876 main(argv)