Support copy'ing a word constant to a word location. Joystick eg.
Chris Pressey
7 years ago
74 | 74 | |
75 | 75 | and sixty-five thousand five hundred and thirty-six word constants, |
76 | 76 | |
77 | 0 | |
78 | 1 | |
77 | word 0 | |
78 | word 1 | |
79 | 79 | ... |
80 | 65535 | |
81 | ||
82 | Note that all byte constants serve double duty as word constants in that | |
83 | context. | |
80 | word 65535 | |
81 | ||
82 | Note that if a word constant is between 256 and 65535, the leading `word` | |
83 | token can be omitted. | |
84 | 84 | |
85 | 85 | ### User-defined ### |
86 | 86 |
0 | word screen @ 1024 | |
1 | byte joy2 @ $dc00 | |
2 | ||
3 | word delta | |
4 | ||
5 | routine read_stick | |
6 | inputs joy2 | |
7 | outputs delta | |
8 | trashes a, x, z, n | |
9 | { | |
10 | ld x, joy2 | |
11 | ld a, x | |
12 | and a, 1 // up | |
13 | if z { | |
14 | copy $ffd8, delta // -40 | |
15 | } else { | |
16 | ld a, x | |
17 | and a, 2 // down | |
18 | if z { | |
19 | copy word 40, delta | |
20 | } else { | |
21 | ld a, x | |
22 | and a, 4 // left | |
23 | if z { | |
24 | copy $ffff, delta // -1 | |
25 | } else { | |
26 | ld a, x | |
27 | and a, 8 // right | |
28 | if z { | |
29 | copy word 1, delta | |
30 | } else { | |
31 | copy word 0, delta | |
32 | } | |
33 | } | |
34 | } | |
35 | } | |
36 | } | |
37 | ||
38 | routine main | |
39 | inputs joy2 | |
40 | outputs delta | |
41 | trashes a, x, z, n, screen | |
42 | { | |
43 | repeat { | |
44 | call read_stick | |
45 | copy delta, screen | |
46 | ld a, 1 | |
47 | } until z | |
48 | } |
118 | 118 | elif isinstance(ref, LocationRef): |
119 | 119 | if ref not in self._meaningful: |
120 | 120 | message = '%s in %s' % (ref.name, self.routine.name) |
121 | if kwargs.get('message'): | |
122 | message += ' (%s)' % kwargs['message'] | |
121 | 123 | raise exception_class(message) |
122 | 124 | else: |
123 | 125 | raise NotImplementedError(ref) |
127 | 129 | for ref in refs: |
128 | 130 | if ref not in self._writeable: |
129 | 131 | message = '%s in %s' % (ref.name, self.routine.name) |
132 | if kwargs.get('message'): | |
133 | message += ' (%s)' % kwargs['message'] | |
130 | 134 | raise exception_class(message) |
131 | 135 | |
132 | 136 | def set_touched(self, *refs): |
269 | 273 | # probably not; if it wasn't meaningful in the first place, it |
270 | 274 | # doesn't really matter if you modified it or not, coming out. |
271 | 275 | for ref in context1.each_meaningful(): |
272 | context2.assert_meaningful(ref, exception_class=InconsistentInitializationError) | |
276 | context2.assert_meaningful( | |
277 | ref, exception_class=InconsistentInitializationError, message='initialized in block 1 but not in block 2' | |
278 | ) | |
273 | 279 | for ref in context2.each_meaningful(): |
274 | context1.assert_meaningful(ref, exception_class=InconsistentInitializationError) | |
280 | context1.assert_meaningful( | |
281 | ref, exception_class=InconsistentInitializationError, message='initialized in block 2 but not in block 1' | |
282 | ) | |
275 | 283 | context.set_from(context1) |
276 | 284 | elif opcode == 'repeat': |
277 | 285 | # it will always be executed at least once, so analyze it having |
275 | 275 | self.emitter.emit(CLI()) |
276 | 276 | elif opcode == 'copy': |
277 | 277 | if src.type == TYPE_BYTE and dest.type == TYPE_BYTE: |
278 | src_label = self.labels[src.name] | |
279 | dest_label = self.labels[dest.name] | |
280 | self.emitter.emit(LDA(Absolute(src_label))) | |
281 | self.emitter.emit(STA(Absolute(dest_label))) | |
278 | if isinstance(src, ConstantRef): | |
279 | raise NotImplementedError | |
280 | else: | |
281 | src_label = self.labels[src.name] | |
282 | dest_label = self.labels[dest.name] | |
283 | self.emitter.emit(LDA(Absolute(src_label))) | |
284 | self.emitter.emit(STA(Absolute(dest_label))) | |
282 | 285 | elif src.type == TYPE_WORD and dest.type == TYPE_WORD: |
283 | src_label = self.labels[src.name] | |
284 | dest_label = self.labels[dest.name] | |
285 | self.emitter.emit(LDA(Absolute(src_label))) | |
286 | self.emitter.emit(STA(Absolute(dest_label))) | |
287 | self.emitter.emit(LDA(Absolute(Offset(src_label, 1)))) | |
288 | self.emitter.emit(STA(Absolute(Offset(dest_label, 1)))) | |
286 | if isinstance(src, ConstantRef): | |
287 | dest_label = self.labels[dest.name] | |
288 | hi = (src.value >> 8) & 255 | |
289 | lo = src.value & 255 | |
290 | self.emitter.emit(LDA(Immediate(Byte(hi)))) | |
291 | self.emitter.emit(STA(Absolute(dest_label))) | |
292 | self.emitter.emit(LDA(Immediate(Byte(lo)))) | |
293 | self.emitter.emit(STA(Absolute(Offset(dest_label, 1)))) | |
294 | else: | |
295 | src_label = self.labels[src.name] | |
296 | dest_label = self.labels[dest.name] | |
297 | self.emitter.emit(LDA(Absolute(src_label))) | |
298 | self.emitter.emit(STA(Absolute(dest_label))) | |
299 | self.emitter.emit(LDA(Absolute(Offset(src_label, 1)))) | |
300 | self.emitter.emit(STA(Absolute(Offset(dest_label, 1)))) | |
289 | 301 | elif isinstance(src.type, VectorType) and isinstance(dest.type, VectorType): |
290 | 302 | src_label = self.labels[src.name] |
291 | 303 | dest_label = self.labels[dest.name] |
137 | 137 | self.scanner.scan() |
138 | 138 | return loc |
139 | 139 | elif self.scanner.on_type('integer literal'): |
140 | loc = ConstantRef(TYPE_BYTE, int(self.scanner.token)) | |
140 | value = int(self.scanner.token) | |
141 | type_ = TYPE_WORD if value > 255 else TYPE_BYTE | |
142 | loc = ConstantRef(type_, value) | |
143 | self.scanner.scan() | |
144 | return loc | |
145 | elif self.scanner.consume('word'): | |
146 | loc = ConstantRef(TYPE_WORD, int(self.scanner.token)) | |
141 | 147 | self.scanner.scan() |
142 | 148 | return loc |
143 | 149 | else: |
218 | 224 | src = self.locexpr() |
219 | 225 | self.scanner.expect(',') |
220 | 226 | dest = self.locexpr() |
221 | return Instr(opcode=opcode, dest=dest, src=src) | |
227 | i = Instr(opcode=opcode, dest=dest, src=src) | |
228 | #print repr(i) | |
229 | return i | |
222 | 230 | elif self.scanner.consume("with"): |
223 | 231 | self.scanner.expect("interrupts") |
224 | 232 | self.scanner.expect("off") |