Add word (constant or memory loc) to pointer (unchecked for now).
Chris Pressey
4 years ago
4 | 4 | --- |
5 | 5 | |
6 | 6 | * Add word (constant or memory location) to word memory location. |
7 | * Add word to pointer (unchecked for now). | |
8 | * Implementation: `--debug` shows some extra info during analysis. | |
7 | 9 | |
8 | 10 | 0.8 |
9 | 11 | --- |
41 | 41 | |
42 | 42 | ### Operations on 16 bit values |
43 | 43 | |
44 | Add word (constant or memory location) to pointer. (Not necessarily range-checked yet though.) | |
45 | ||
46 | 44 | Compare word (constant or memory location) with memory location or pointer. (Maybe?) |
47 | 45 | |
48 | 46 | And then write a little demo "game" where you can move a block around the screen with |
254 | 254 | context.assert_meaningful(src) |
255 | 255 | context.set_written(dest) |
256 | 256 | elif opcode == 'add': |
257 | context.assert_meaningful(src, dest, FLAG_C) | |
257 | 258 | if src.type == TYPE_BYTE: |
258 | 259 | self.assert_type(TYPE_BYTE, src, dest) |
259 | context.assert_meaningful(src, dest, FLAG_C) | |
260 | 260 | context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) |
261 | 261 | else: |
262 | self.assert_type(TYPE_WORD, src, dest) | |
263 | context.assert_meaningful(src, dest, FLAG_C) | |
264 | context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) | |
265 | context.set_touched(REG_A) | |
266 | context.set_unmeaningful(REG_A) | |
262 | self.assert_type(TYPE_WORD, src) | |
263 | if dest.type == TYPE_WORD: | |
264 | context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) | |
265 | context.set_touched(REG_A) | |
266 | context.set_unmeaningful(REG_A) | |
267 | elif isinstance(dest.type, PointerType): | |
268 | context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) | |
269 | context.set_touched(REG_A) | |
270 | context.set_unmeaningful(REG_A) | |
271 | else: | |
272 | self.assert_type(TYPE_WORD, dest) | |
267 | 273 | elif opcode == 'sub': |
268 | 274 | self.assert_type(TYPE_BYTE, src, dest) |
269 | 275 | context.assert_meaningful(src, dest, FLAG_C) |
146 | 146 | self.emitter.emit(ADC(Immediate(Byte(src.value)))) |
147 | 147 | else: |
148 | 148 | self.emitter.emit(ADC(Absolute(self.labels[src.name]))) |
149 | elif isinstance(dest, LocationRef) and dest.type == TYPE_WORD and src.type == TYPE_WORD: | |
149 | elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD: | |
150 | 150 | if isinstance(src, ConstantRef): |
151 | 151 | dest_label = self.labels[dest.name] |
152 | 152 | self.emitter.emit(LDA(Absolute(dest_label))) |
164 | 164 | self.emitter.emit(LDA(Absolute(Offset(dest_label, 1)))) |
165 | 165 | self.emitter.emit(ADC(Absolute(Offset(src_label, 1)))) |
166 | 166 | self.emitter.emit(STA(Absolute(Offset(dest_label, 1)))) |
167 | else: | |
168 | raise UnsupportedOpcodeError(instr) | |
169 | elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and isinstance(dest.type, PointerType): | |
170 | if isinstance(src, ConstantRef): | |
171 | dest_label = self.labels[dest.name] # this. is. zero-page. | |
172 | self.emitter.emit(LDA(ZeroPage(dest_label))) | |
173 | self.emitter.emit(ADC(Immediate(Byte(src.low_byte())))) | |
174 | self.emitter.emit(STA(ZeroPage(dest_label))) | |
175 | self.emitter.emit(LDA(ZeroPage(Offset(dest_label, 1)))) | |
176 | self.emitter.emit(ADC(Immediate(Byte(src.high_byte())))) | |
177 | self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1)))) | |
178 | elif isinstance(src, LocationRef): | |
179 | src_label = self.labels[src.name] | |
180 | dest_label = self.labels[dest.name] # this. is. zero-page. | |
181 | self.emitter.emit(LDA(ZeroPage(dest_label))) | |
182 | self.emitter.emit(ADC(Absolute(src_label))) | |
183 | self.emitter.emit(STA(ZeroPage(dest_label))) | |
184 | self.emitter.emit(LDA(ZeroPage(Offset(dest_label, 1)))) | |
185 | self.emitter.emit(ADC(Absolute(Offset(src_label, 1)))) | |
186 | self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1)))) | |
167 | 187 | else: |
168 | 188 | raise UnsupportedOpcodeError(instr) |
169 | 189 | else: |
436 | 436 | | { |
437 | 437 | | st off, c |
438 | 438 | | add score, delta |
439 | | } | |
440 | ? ForbiddenWriteError: a in main | |
441 | ||
442 | You can `add` a word memory location, or a constant, to a pointer. | |
443 | ||
444 | | pointer ptr | |
445 | | word delta | |
446 | | routine main | |
447 | | inputs ptr, delta | |
448 | | outputs ptr | |
449 | | trashes a, c, z, v, n | |
450 | | { | |
451 | | st off, c | |
452 | | add ptr, delta | |
453 | | add ptr, word 1 | |
454 | | } | |
455 | = ok | |
456 | ||
457 | `add`ing a word memory location, or a constant, to a pointer, trashes `a`. | |
458 | ||
459 | | pointer ptr | |
460 | | word delta | |
461 | | routine main | |
462 | | inputs ptr, delta | |
463 | | outputs ptr | |
464 | | trashes c, z, v, n | |
465 | | { | |
466 | | st off, c | |
467 | | add ptr, delta | |
468 | | add ptr, word 1 | |
439 | 469 | | } |
440 | 470 | ? ForbiddenWriteError: a in main |
441 | 471 |
436 | 436 | | copy [ptr] + y, foo |
437 | 437 | | } |
438 | 438 | = 00c0a000a91085fea9c085ffb1fe8d12c060 |
439 | ||
440 | Add a word memory location, and a literal word, to a pointer, and then read through it. | |
441 | Note that this is *not* range-checked. (Yet.) | |
442 | ||
443 | | buffer[2048] buf | |
444 | | pointer ptr @ 254 | |
445 | | byte foo | |
446 | | word delta | |
447 | | | |
448 | | routine main | |
449 | | inputs buf | |
450 | | outputs y, foo, delta | |
451 | | trashes a, z, n, ptr | |
452 | | { | |
453 | | copy 619, delta | |
454 | | ld y, 0 | |
455 | | copy ^buf, ptr | |
456 | | add ptr, delta | |
457 | | add ptr, word 1 | |
458 | | copy [ptr] + y, foo | |
459 | | } | |
460 | = 00c0a9028d38c0a96b8d39c0a000a93485fea9c085ffa5fe6d38c085fea5ff6d39c085ffa5fe690185fea5ff690085ffb1fe8d36c060 |