git @ Cat's Eye Technologies SixtyPical / 22c58ba
Improve evaluator internals. Finish test suite for analysis. Chris Pressey 6 years ago
4 changed file(s) with 198 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
5757
5858 if options.execute:
5959 context = eval_program(program)
60 for key, value in sorted(context.iteritems()):
61 print "%s: %s" % (key, value)
60 print str(context)
157157 context.assert_writeable(dest, FLAG_Z, FLAG_N)
158158 context.set_initialized(dest, FLAG_Z, FLAG_N)
159159 elif opcode in ('shl', 'shr'):
160 context.assert_initialized(dest)
160 context.assert_initialized(dest, FLAG_C)
161161 context.assert_writeable(dest, FLAG_Z, FLAG_N, FLAG_C)
162162 context.set_initialized(dest, FLAG_Z, FLAG_N, FLAG_C)
163163 elif opcode == 'call':
00 # encoding: UTF-8
11
22 from sixtypical.ast import Program, Routine, Block, Instr
3 from sixtypical.model import ConstantRef, LocationRef
3 from sixtypical.model import (
4 ConstantRef, LocationRef,
5 REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
6 )
47
58
6 # TODO: should not inherit from dict
7 class Context(dict):
9 class Context(object):
10 def __init__(self):
11 self._store = {}
12
13 def __str__(self):
14 return '\n'.join("%s: %s" % p for p in sorted(self._store.iteritems()))
15
816 def get(self, ref):
917 if isinstance(ref, ConstantRef):
1018 return ref.value
1119 elif isinstance(ref, LocationRef):
12 return self[ref.name]
20 return self._store[ref.name]
1321 else:
1422 raise ValueError(ref)
1523
1624 def set(self, ref, value):
1725 assert isinstance(ref, LocationRef)
18 self[ref.name] = value
26 self._store[ref.name] = value
1927
2028
2129 def eval_program(program):
2230 assert isinstance(program, Program)
2331 routines = {r.name: r for r in program.routines}
24 context = Context({
25 'a': 0, 'x': 0, 'y': 0,
26 'c': 0, 'n': 0, 'z': 0, 'v': 0
27 })
32 context = Context()
33 for ref in (REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C):
34 context.set(ref, 0)
2835 eval_routine(routines['main'], context, routines)
2936 return context
3037
4855
4956 if opcode == 'ld':
5057 result = context.get(src)
51 context['z'] = 1 if result == 0 else 0
52 context['n'] = 1 if result & 128 else 0
58 context.set(FLAG_Z, 1 if result == 0 else 0)
59 context.set(FLAG_N, 1 if result & 128 else 0)
5360 context.set(dest, result)
5461 elif opcode == 'st':
5562 context.set(dest, context.get(src))
5663 elif opcode == 'add':
57 carry = context['c']
64 carry = context.get(FLAG_C)
5865 val = context.get(src)
5966 now = context.get(dest)
6067 result = now + val + carry
6168 if result > 255:
6269 result &= 255
63 context['c'] = 1
70 context.set(FLAG_C, 1)
6471 else:
65 context['c'] = 0
66 context['z'] = 1 if result == 0 else 0
67 context['n'] = 1 if result & 128 else 0
72 context.set(FLAG_C, 0)
73 context.set(FLAG_Z, 1 if result == 0 else 0)
74 context.set(FLAG_N, 1 if result & 128 else 0)
6875 context.set(dest, result)
6976 elif opcode == 'sub':
70 carry = context['c']
77 carry = context.get(FLAG_C)
7178 val = context.get(src)
7279 now = context.get(dest)
7380 result = now - val - carry
7481 if result < 0:
7582 result &= 255
76 context['c'] = 1
83 context.set(FLAG_C, 1)
7784 else:
78 context['c'] = 0
79 context['z'] = 1 if result == 0 else 0
80 context['n'] = 1 if result & 128 else 0
85 context.set(FLAG_C, 0)
86 context.set(FLAG_Z, 1 if result == 0 else 0)
87 context.set(FLAG_N, 1 if result & 128 else 0)
8188 context.set(dest, result)
8289 elif opcode == 'inc':
8390 val = context.get(dest)
8491 result = (val + 1) & 255
85 context['z'] = 1 if result == 0 else 0
86 context['n'] = 1 if result & 128 else 0
92 context.set(FLAG_Z, 1 if result == 0 else 0)
93 context.set(FLAG_N, 1 if result & 128 else 0)
8794 context.set(dest, result)
8895 elif opcode == 'dec':
8996 val = context.get(dest)
9097 result = (val - 1) & 255
91 context['z'] = 1 if result == 0 else 0
92 context['n'] = 1 if result & 128 else 0
98 context.set(FLAG_Z, 1 if result == 0 else 0)
99 context.set(FLAG_N, 1 if result & 128 else 0)
93100 context.set(dest, result)
94101 elif opcode == 'cmp':
95102 val = context.get(src)
96103 now = context.get(dest)
97104 result = now - val
98 context['z'] = 1 if result == 0 else 0
99 context['n'] = 1 if result & 128 else 0
105 context.set(FLAG_Z, 1 if result == 0 else 0)
106 context.set(FLAG_N, 1 if result & 128 else 0)
100107 if result < 0:
101108 result &= 255
102 context['c'] = 1
109 context.set(FLAG_C, 1)
103110 else:
104 context['c'] = 0
111 context.set(FLAG_C, 0)
105112 elif opcode == 'and':
106113 result = context.get(dest) & context.get(src)
107 context['z'] = 1 if result == 0 else 0
108 context['n'] = 1 if result & 128 else 0
114 context.set(FLAG_Z, 1 if result == 0 else 0)
115 context.set(FLAG_N, 1 if result & 128 else 0)
109116 context.set(dest, result)
110117 elif opcode == 'or':
111118 result = context.get(dest) | context.get(src)
112 context['z'] = 1 if result == 0 else 0
113 context['n'] = 1 if result & 128 else 0
119 context.set(FLAG_Z, 1 if result == 0 else 0)
120 context.set(FLAG_N, 1 if result & 128 else 0)
114121 context.set(dest, result)
115122 elif opcode == 'xor':
116123 result = context.get(dest) ^ context.get(src)
117 context['z'] = 1 if result == 0 else 0
118 context['n'] = 1 if result & 128 else 0
124 context.set(FLAG_Z, 1 if result == 0 else 0)
125 context.set(FLAG_N, 1 if result & 128 else 0)
119126 context.set(dest, result)
120127 elif opcode == 'shl':
121128 val = context.get(dest)
122 carry = context['c']
123 context['c'] = 1 if val & 128 else 0
129 carry = context.get(FLAG_C)
130 context.set(FLAG_C, 1 if val & 128 else 0)
124131 result = ((val << 1) + carry) & 255
125 context['z'] = 1 if result == 0 else 0
126 context['n'] = 1 if result & 128 else 0
132 context.set(FLAG_Z, 1 if result == 0 else 0)
133 context.set(FLAG_N, 1 if result & 128 else 0)
127134 context.set(dest, result)
128135 elif opcode == 'shr':
129136 val = context.get(dest)
130 carry = context['c']
131 context['c'] = 1 if val & 1 else 0
137 carry = context.get(FLAG_C)
138 context.set(FLAG_C, 1 if val & 1 else 0)
132139 result = (val >> 1) + (carry * 128)
133 context['z'] = 1 if result == 0 else 0
134 context['n'] = 1 if result & 128 else 0
140 context.set(FLAG_Z, 1 if result == 0 else 0)
141 context.set(FLAG_N, 1 if result & 128 else 0)
135142 context.set(dest, result)
136143 elif opcode == 'call':
137144 eval_routine(routines[instr.name], context, routines)
348348
349349 ### cmp ###
350350
351 TODO: write some tests
351 Some rudimentary tests for cmp.
352
353 | routine main
354 | inputs a
355 | trashes z, c, n
356 | {
357 | cmp a, 4
358 | }
359 = ok
360
361 | routine main
362 | inputs a
363 | trashes z, n
364 | {
365 | cmp a, 4
366 | }
367 ? IllegalWriteError: c
368
369 | routine main
370 | trashes z, c, n
371 | {
372 | cmp a, 4
373 | }
374 ? UninitializedAccessError: a
352375
353376 ### and ###
354377
355 TODO: write some tests
378 Some rudimentary tests for and.
379
380 | routine main
381 | inputs a
382 | outputs a, z, n
383 | {
384 | and a, 4
385 | }
386 = ok
387
388 | routine main
389 | inputs a
390 | trashes z, n
391 | {
392 | and a, 4
393 | }
394 ? IllegalWriteError: a
395
396 | routine main
397 | trashes z, n
398 | {
399 | and a, 4
400 | }
401 ? UninitializedAccessError: a
356402
357403 ### or ###
358404
359 TODO: write some tests
405 Writing unit tests on a train. Wow.
406
407 | routine main
408 | inputs a
409 | outputs a, z, n
410 | {
411 | or a, 4
412 | }
413 = ok
414
415 | routine main
416 | inputs a
417 | trashes z, n
418 | {
419 | or a, 4
420 | }
421 ? IllegalWriteError: a
422
423 | routine main
424 | trashes z, n
425 | {
426 | or a, 4
427 | }
428 ? UninitializedAccessError: a
360429
361430 ### xor ###
362431
363 TODO: write some tests
432 Writing unit tests on a train. Wow.
433
434 | routine main
435 | inputs a
436 | outputs a, z, n
437 | {
438 | xor a, 4
439 | }
440 = ok
441
442 | routine main
443 | inputs a
444 | trashes z, n
445 | {
446 | xor a, 4
447 | }
448 ? IllegalWriteError: a
449
450 | routine main
451 | trashes z, n
452 | {
453 | xor a, 4
454 | }
455 ? UninitializedAccessError: a
364456
365457 ### shl ###
366458
367 TODO: write some tests
459 Some rudimentary tests for shl.
460
461 | routine main
462 | inputs a, c
463 | outputs a, c, z, n
464 | {
465 | shl a
466 | }
467 = ok
468
469 | routine main
470 | inputs a, c
471 | outputs c, z, n
472 | {
473 | shl a
474 | }
475 ? IllegalWriteError: a
476
477 | routine main
478 | inputs a
479 | outputs a, c, z, n
480 | {
481 | shl a
482 | }
483 ? UninitializedAccessError: c
368484
369485 ### shr ###
370486
371 TODO: write some tests
487 Some rudimentary tests for shr.
488
489 | routine main
490 | inputs a, c
491 | outputs a, c, z, n
492 | {
493 | shr a
494 | }
495 = ok
496
497 | routine main
498 | inputs a, c
499 | outputs c, z, n
500 | {
501 | shr a
502 | }
503 ? IllegalWriteError: a
504
505 | routine main
506 | inputs a
507 | outputs a, c, z, n
508 | {
509 | shr a
510 | }
511 ? UninitializedAccessError: c
372512
373513 ### call ###
374514