git @ Cat's Eye Technologies SixtyPical / ca1c877
Support indirect refs in st, e.g. `st a, [ptr] + y`. Chris Pressey 3 years ago
7 changed file(s) with 95 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
33 0.12
44 ----
55
6 * `copy` is now understood to trash `a`, thus `copy ..., a` is not valid.
7 Indirect addressing is supported in `ld`, as in `ld a, [ptr] + y`, to compensate.
6 * `copy` is now understood to trash `a`, thus it is not valid to use it in `copy`.
7 To compensate, indirect addressing is supported in `ld` and `st`, for example,
8 as `ld a, [ptr] + y` and `st a, [ptr] + y`.
89 * Implements the "union rule for trashes" when analyzing `if` blocks.
910 * Even if we `goto` another routine, we can't trash an output.
1011 * Fixed bug where `trash` was not marking the location as being virtually altered.
239239
240240 There is another mode of `ld` which reads into `a` indirectly through a pointer.
241241
242 copy [<src-memory-location>] + y, <dest-memory-location>
242 ld a, [<src-memory-location>] + y
243243
244244 The memory location in this syntax must be a pointer.
245245
264264 changed by this instruction (unless of course dest is a flag.)
265265
266266 If and only if dest is a byte table, the index-memory-location must be given.
267
268 There is another mode of `st` which write `a` into memory, indirectly through
269 a pointer.
270
271 st a, [<dest-memory-location>] + y
272
273 The memory location in this syntax must be a pointer.
274
275 This syntax copies the constents of the `a` register into
276 the contents of memory at the pointer (offset by the `y` register).
277
278 In addition to the constraints above, `y` must be initialized before
279 this mode is used.
267280
268281 ### copy ###
269282
272272 context.assert_meaningful(src)
273273 context.set_written(dest, FLAG_Z, FLAG_N)
274274 elif opcode == 'st':
275 if instr.index:
276 if src.type == TYPE_BYTE and TableType.is_a_table_type(dest.type, TYPE_BYTE):
277 pass
278 else:
279 raise TypeMismatchError((src, dest))
280 context.assert_meaningful(instr.index)
275 if isinstance(dest, IndexedRef):
276 if src.type == TYPE_BYTE and TableType.is_a_table_type(dest.ref.type, TYPE_BYTE):
277 pass
278 else:
279 raise TypeMismatchError((src, dest))
280 context.assert_meaningful(dest.index)
281 context.set_written(dest.ref)
282 elif isinstance(dest, IndirectRef):
283 # copying this analysis from the matching branch in `copy`, below
284 if isinstance(dest.ref.type, PointerType) and src.type == TYPE_BYTE:
285 pass
286 else:
287 raise TypeMismatchError((src, dest))
288 context.assert_meaningful(dest.ref, REG_Y)
289 context.set_written(dest.ref)
281290 elif src.type != dest.type:
282291 raise TypeMismatchError('%r and %r in %s' %
283292 (src, dest, self.current_routine.name)
284293 )
294 else:
295 context.set_written(dest)
285296 context.assert_meaningful(src)
286 context.set_written(dest)
287297 elif opcode == 'add':
288298 context.assert_meaningful(src, dest, FLAG_C)
289299 if src.type == TYPE_BYTE:
136136 self.emitter.emit(LDA(AbsoluteY(self.labels[src.name])))
137137 elif isinstance(src, IndirectRef) and isinstance(src.ref.type, PointerType):
138138 self.emitter.emit(LDA(IndirectY(self.labels[src.ref.name])))
139 elif isinstance(src, IndirectRef) and src.index == REG_Y:
140 self.emitter.emit(LDA(AbsoluteY(self.labels[src.name])))
141139 else:
142140 self.emitter.emit(LDA(Absolute(self.labels[src.name])))
143141 elif dest == REG_X:
171169 REG_X: STX,
172170 REG_Y: STY
173171 }.get(src, None)
174 mode_cls = {
175 REG_X: AbsoluteX,
176 REG_Y: AbsoluteY,
177 None: Absolute
178 }.get(instr.index, None)
172
173 if isinstance(dest, IndexedRef):
174 mode_cls = {
175 REG_X: AbsoluteX,
176 REG_Y: AbsoluteY,
177 }[dest.index]
178 label = self.labels[dest.ref.name]
179 elif isinstance(dest, IndirectRef) and isinstance(dest.ref.type, PointerType):
180 mode_cls = IndirectY
181 label = self.labels[dest.ref.name]
182 else:
183 mode_cls = Absolute
184 label = self.labels[dest.name]
185
179186 if op_cls is None or mode_cls is None:
180187 raise UnsupportedOpcodeError(instr)
181 self.emitter.emit(op_cls(mode_cls(self.labels[dest.name])))
188 self.emitter.emit(op_cls(mode_cls(label)))
182189 elif opcode == 'add':
183190 if dest == REG_A:
184191 if isinstance(src, ConstantRef):
338338 self.scanner.scan()
339339 src = self.locexpr()
340340 self.scanner.expect(',')
341 dest = self.locexpr()
342 index = None
343 if self.scanner.consume('+'):
344 index = self.locexpr()
345 return Instr(opcode=opcode, dest=dest, src=src, index=index)
341 dest = self.indlocexpr()
342 return Instr(opcode=opcode, dest=dest, src=src, index=None)
346343 elif self.scanner.token in ("shl", "shr", "inc", "dec"):
347344 opcode = self.scanner.token
348345 self.scanner.scan()
17621762 | }
17631763 = ok
17641764
1765 Write the `a` register through a pointer. Note that this is done with `st`,
1766 not `copy`.
1767
1768 | buffer[2048] buf
1769 | pointer ptr
1770 | byte foo
1771 |
1772 | routine main
1773 | inputs buf
1774 | outputs buf
1775 | trashes a, y, z, n, ptr
1776 | {
1777 | ld y, 0
1778 | copy ^buf, ptr
1779 | ld a, 255
1780 | st a, [ptr] + y
1781 | }
1782 = ok
1783
17651784 ### routines ###
17661785
17671786 Routines are constants. You need not, and in fact cannot, specify a constant
857857 = $081C LDA ($FE),Y
858858 = $081E RTS
859859
860 Write the `a` register through a pointer.
861
862 | buffer[2048] buf
863 | pointer ptr @ 254
864 | byte foo
865 |
866 | routine main
867 | inputs buf
868 | outputs buf
869 | trashes a, y, z, n, ptr
870 | {
871 | ld y, 0
872 | copy ^buf, ptr
873 | ld a, 255
874 | st a, [ptr] + y
875 | }
876 = $080D LDY #$00
877 = $080F LDA #$1C
878 = $0811 STA $FE
879 = $0813 LDA #$08
880 = $0815 STA $FF
881 = $0817 LDA #$FF
882 = $0819 STA ($FE),Y
883 = $081B RTS
884
860885 Add a word memory location, and a literal word, to a pointer, and then read through it.
861886 Note that this is *not* range-checked. (Yet.)
862887