Mercurial > repos > blastem
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) |