Make ld parse to a IndexedRef or IndirectRef (latter still todo.)
Chris Pressey
4 years ago
0 | 0 | SixtyPical |
1 | 1 | ========== |
2 | 2 | |
3 | _Version 0.11. Work-in-progress, everything is subject to change._ | |
3 | _Version 0.12. Work-in-progress, everything is subject to change._ | |
4 | 4 | |
5 | 5 | SixtyPical is a very low-level programming language, similar to 6502 assembly, |
6 | 6 | with static analysis through abstract interpretation. |
126 | 126 | if kwargs.get('message'): |
127 | 127 | message += ' (%s)' % kwargs['message'] |
128 | 128 | raise exception_class(message) |
129 | elif isinstance(ref, IndexedRef): | |
130 | self.assert_meaningful(ref.ref, **kwargs) | |
131 | self.assert_meaningful(ref.index, **kwargs) | |
129 | 132 | else: |
130 | 133 | raise NotImplementedError(ref) |
131 | 134 | |
235 | 238 | src = instr.src |
236 | 239 | |
237 | 240 | if opcode == 'ld': |
238 | if instr.index: | |
239 | if TableType.is_a_table_type(src.type, TYPE_BYTE) and dest.type == TYPE_BYTE: | |
241 | if isinstance(src, IndexedRef): | |
242 | if TableType.is_a_table_type(src.ref.type, TYPE_BYTE) and dest.type == TYPE_BYTE: | |
240 | 243 | pass |
241 | 244 | else: |
242 | 245 | raise TypeMismatchError('%s and %s in %s' % |
243 | (src.name, dest.name, self.current_routine.name) | |
246 | (src.ref.name, dest.name, self.current_routine.name) | |
244 | 247 | ) |
245 | context.assert_meaningful(instr.index) | |
248 | context.assert_meaningful(src.index) | |
249 | elif isinstance(src, IndirectRef): | |
250 | raise NotImplementedError | |
246 | 251 | elif src.type != dest.type: |
247 | 252 | raise TypeMismatchError('%s and %s in %s' % |
248 | 253 | (src.name, dest.name, self.current_routine.name) |
351 | 356 | context.assert_meaningful(src) |
352 | 357 | |
353 | 358 | elif opcode == 'copy': |
359 | if dest == REG_A: | |
360 | raise ForbiddenWriteError("{} cannot be used as destination for copy".format(dest)) | |
361 | ||
354 | 362 | # 1. check that their types are compatible |
355 | 363 | |
356 | 364 | if isinstance(src, AddressRef) and isinstance(dest, LocationRef): |
130 | 130 | self.emitter.emit(TYA()) |
131 | 131 | elif isinstance(src, ConstantRef): |
132 | 132 | self.emitter.emit(LDA(Immediate(Byte(src.value)))) |
133 | elif instr.index == REG_X: | |
133 | elif isinstance(src, IndexedRef) and src.index == REG_X: | |
134 | 134 | self.emitter.emit(LDA(AbsoluteX(self.labels[src.name]))) |
135 | elif instr.index == REG_Y: | |
135 | elif isinstance(src, IndexedRef) and src.index == REG_Y: | |
136 | 136 | self.emitter.emit(LDA(AbsoluteY(self.labels[src.name]))) |
137 | 137 | else: |
138 | 138 | self.emitter.emit(LDA(Absolute(self.labels[src.name]))) |
141 | 141 | self.emitter.emit(TAX()) |
142 | 142 | elif isinstance(src, ConstantRef): |
143 | 143 | self.emitter.emit(LDX(Immediate(Byte(src.value)))) |
144 | elif instr.index == REG_Y: | |
144 | elif isinstance(src, IndexedRef) and src.index == REG_Y: | |
145 | 145 | self.emitter.emit(LDX(AbsoluteY(self.labels[src.name]))) |
146 | 146 | else: |
147 | 147 | self.emitter.emit(LDX(Absolute(self.labels[src.name]))) |
150 | 150 | self.emitter.emit(TAY()) |
151 | 151 | elif isinstance(src, ConstantRef): |
152 | 152 | self.emitter.emit(LDY(Immediate(Byte(src.value)))) |
153 | elif instr.index == REG_X: | |
153 | elif isinstance(src, IndexedRef) and src.index == REG_X: | |
154 | 154 | self.emitter.emit(LDY(AbsoluteX(self.labels[src.name]))) |
155 | 155 | else: |
156 | 156 | self.emitter.emit(LDY(Absolute(self.labels[src.name]))) |
201 | 201 | |
202 | 202 | @property |
203 | 203 | def name(self): |
204 | return '{}+{}'.format(self.ref.name, self.index.name) | |
204 | return self.ref.name | |
205 | #return '{}+{}'.format(self.ref.name, self.index.name) | |
205 | 206 | |
206 | 207 | def is_constant(self): |
207 | 208 | return False |
315 | 315 | self.scanner.expect('forever') |
316 | 316 | return Instr(opcode='repeat', dest=None, src=src, |
317 | 317 | block=block, inverted=inverted) |
318 | elif self.scanner.token in ("ld", "add", "sub", "cmp", "and", "or", "xor"): | |
318 | elif self.scanner.token in ("ld",): | |
319 | # the same as add, sub, cmp etc below, except supports an indlocexpr for the src | |
320 | opcode = self.scanner.token | |
321 | self.scanner.scan() | |
322 | dest = self.locexpr() | |
323 | self.scanner.expect(',') | |
324 | src = self.indlocexpr() | |
325 | return Instr(opcode=opcode, dest=dest, src=src, index=None) | |
326 | elif self.scanner.token in ("add", "sub", "cmp", "and", "or", "xor"): | |
319 | 327 | opcode = self.scanner.token |
320 | 328 | self.scanner.scan() |
321 | 329 | dest = self.locexpr() |
1461 | 1461 | | } |
1462 | 1462 | = ok |
1463 | 1463 | |
1464 | The understanding is that, because `copy` trashes `a`, `a` cannot be used | |
1465 | as the destination of a `copy`. | |
1466 | ||
1467 | | byte source : 0 | |
1468 | | byte dest | |
1469 | | | |
1470 | | routine main | |
1471 | | inputs source | |
1472 | | outputs dest | |
1473 | | trashes a, z, n | |
1474 | | { | |
1475 | | copy source, a | |
1476 | | } | |
1477 | ? ForbiddenWriteError | |
1478 | ||
1464 | 1479 | Can `copy` from a `word` to a `word`. |
1465 | 1480 | |
1466 | 1481 | | word source : 0 |
1503 | 1518 | | } |
1504 | 1519 | ? TypeMismatchError |
1505 | 1520 | |
1506 | ### copy[] ### | |
1507 | ||
1508 | Buffers and pointers. | |
1521 | ### Buffers and pointers ### | |
1509 | 1522 | |
1510 | 1523 | Note that `^buf` is a constant value, so it by itself does not require `buf` to be |
1511 | 1524 | listed in any input/output sets. |
1584 | 1597 | | ld y, 0 |
1585 | 1598 | | copy ^buf, ptr |
1586 | 1599 | | copy [ptr] + y, foo |
1600 | | } | |
1601 | = ok | |
1602 | ||
1603 | Read through a pointer to the `a` register. Note that | |
1604 | this is done with `ld`, not `copy`. | |
1605 | ||
1606 | | buffer[2048] buf | |
1607 | | pointer ptr | |
1608 | | byte foo | |
1609 | | | |
1610 | | routine main | |
1611 | | inputs buf | |
1612 | | outputs foo | |
1613 | | trashes a, y, z, n, ptr | |
1614 | | { | |
1615 | | ld y, 0 | |
1616 | | copy ^buf, ptr | |
1617 | | ld a, [ptr] + y | |
1587 | 1618 | | } |
1588 | 1619 | = ok |
1589 | 1620 |