Implement indirect JSRs with trampolines in theory; doesn't work.
Chris Pressey
6 years ago
13 | 13 | |
14 | 14 | import codecs |
15 | 15 | from optparse import OptionParser |
16 | from pprint import pprint | |
16 | 17 | import sys |
17 | 18 | import traceback |
18 | 19 | |
83 | 84 | compiler = Compiler(emitter) |
84 | 85 | compiler.compile_program(program) |
85 | 86 | if options.debug: |
86 | print repr(emitter.accum) | |
87 | pprint(emitter.accum) | |
87 | 88 | else: |
88 | 89 | emitter.serialize(fh) |
89 | 90 |
0 | vector foo outputs x trashes z, n | |
0 | vector print | |
1 | trashes a, z, n | |
1 | 2 | |
2 | routine bar outputs x trashes z, n { | |
3 | ld x, 200 | |
3 | routine chrout | |
4 | inputs a | |
5 | trashes a | |
6 | @ 65490 | |
7 | ||
8 | routine printa | |
9 | trashes a, z, n | |
10 | { | |
11 | ld a, 65 | |
12 | call chrout | |
4 | 13 | } |
5 | 14 | |
6 | routine main inputs bar outputs x, foo trashes a, z, n { | |
7 | copy bar, foo | |
8 | call foo | |
15 | routine printb | |
16 | trashes a, z, n | |
17 | { | |
18 | ld a, 66 | |
19 | call chrout | |
9 | 20 | } |
21 | ||
22 | routine main | |
23 | inputs printa, printb | |
24 | trashes print, a, z, n | |
25 | { | |
26 | copy printa, print | |
27 | call print | |
28 | copy printb, print | |
29 | call print | |
30 | } |
29 | 29 | self.emitter = emitter |
30 | 30 | self.routines = {} |
31 | 31 | self.labels = {} |
32 | self.trampolines = {} # Location -> Label | |
32 | 33 | |
33 | 34 | def compile_program(self, program): |
34 | 35 | assert isinstance(program, Program) |
51 | 52 | if routine.name != 'main': |
52 | 53 | self.compile_routine(routine) |
53 | 54 | |
55 | for location, label in self.trampolines.iteritems(): | |
56 | self.emitter.resolve_label(label) | |
57 | self.emitter.emit(JMP(Indirect(self.labels[location.name]))) | |
58 | ||
54 | 59 | for defn in program.defns: |
55 | 60 | if defn.addr is None: |
56 | 61 | label = self.labels[defn.name] |
57 | 62 | self.emitter.resolve_bss_label(label) |
63 | ||
58 | 64 | |
59 | 65 | def compile_routine(self, routine): |
60 | 66 | assert isinstance(routine, Routine) |
197 | 203 | if isinstance(location.type, RoutineType): |
198 | 204 | self.emitter.emit(JSR(Absolute(label))) |
199 | 205 | elif isinstance(location.type, VectorType): |
200 | # XXX NOT QUITE RIGHT, IS IT? | |
201 | # We need to simulate an indirect JSR! | |
202 | self.emitter.emit(JMP(Indirect(label))) | |
206 | trampoline = self.trampolines.setdefault( | |
207 | location, Label(location.name + '_trampoline') | |
208 | ) | |
209 | self.emitter.emit(JSR(Absolute(trampoline))) | |
203 | 210 | else: |
204 | 211 | raise NotImplementedError |
205 | 212 | elif opcode == 'goto': |