git @ Cat's Eye Technologies SixtyPical / 34daad0
Make ld parse to a IndexedRef or IndirectRef (latter still todo.) Chris Pressey 3 years ago
7 changed file(s) with 63 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
00 SixtyPical
11 ==========
22
3 _Version 0.11. Work-in-progress, everything is subject to change._
3 _Version 0.12. Work-in-progress, everything is subject to change._
44
55 SixtyPical is a very low-level programming language, similar to 6502 assembly,
66 with static analysis through abstract interpretation.
126126 if kwargs.get('message'):
127127 message += ' (%s)' % kwargs['message']
128128 raise exception_class(message)
129 elif isinstance(ref, IndexedRef):
130 self.assert_meaningful(ref.ref, **kwargs)
131 self.assert_meaningful(ref.index, **kwargs)
129132 else:
130133 raise NotImplementedError(ref)
131134
235238 src = instr.src
236239
237240 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:
240243 pass
241244 else:
242245 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)
244247 )
245 context.assert_meaningful(instr.index)
248 context.assert_meaningful(src.index)
249 elif isinstance(src, IndirectRef):
250 raise NotImplementedError
246251 elif src.type != dest.type:
247252 raise TypeMismatchError('%s and %s in %s' %
248253 (src.name, dest.name, self.current_routine.name)
351356 context.assert_meaningful(src)
352357
353358 elif opcode == 'copy':
359 if dest == REG_A:
360 raise ForbiddenWriteError("{} cannot be used as destination for copy".format(dest))
361
354362 # 1. check that their types are compatible
355363
356364 if isinstance(src, AddressRef) and isinstance(dest, LocationRef):
130130 self.emitter.emit(TYA())
131131 elif isinstance(src, ConstantRef):
132132 self.emitter.emit(LDA(Immediate(Byte(src.value))))
133 elif instr.index == REG_X:
133 elif isinstance(src, IndexedRef) and src.index == REG_X:
134134 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:
136136 self.emitter.emit(LDA(AbsoluteY(self.labels[src.name])))
137137 else:
138138 self.emitter.emit(LDA(Absolute(self.labels[src.name])))
141141 self.emitter.emit(TAX())
142142 elif isinstance(src, ConstantRef):
143143 self.emitter.emit(LDX(Immediate(Byte(src.value))))
144 elif instr.index == REG_Y:
144 elif isinstance(src, IndexedRef) and src.index == REG_Y:
145145 self.emitter.emit(LDX(AbsoluteY(self.labels[src.name])))
146146 else:
147147 self.emitter.emit(LDX(Absolute(self.labels[src.name])))
150150 self.emitter.emit(TAY())
151151 elif isinstance(src, ConstantRef):
152152 self.emitter.emit(LDY(Immediate(Byte(src.value))))
153 elif instr.index == REG_X:
153 elif isinstance(src, IndexedRef) and src.index == REG_X:
154154 self.emitter.emit(LDY(AbsoluteX(self.labels[src.name])))
155155 else:
156156 self.emitter.emit(LDY(Absolute(self.labels[src.name])))
201201
202202 @property
203203 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)
205206
206207 def is_constant(self):
207208 return False
315315 self.scanner.expect('forever')
316316 return Instr(opcode='repeat', dest=None, src=src,
317317 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"):
319327 opcode = self.scanner.token
320328 self.scanner.scan()
321329 dest = self.locexpr()
14611461 | }
14621462 = ok
14631463
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
14641479 Can `copy` from a `word` to a `word`.
14651480
14661481 | word source : 0
15031518 | }
15041519 ? TypeMismatchError
15051520
1506 ### copy[] ###
1507
1508 Buffers and pointers.
1521 ### Buffers and pointers ###
15091522
15101523 Note that `^buf` is a constant value, so it by itself does not require `buf` to be
15111524 listed in any input/output sets.
15841597 | ld y, 0
15851598 | copy ^buf, ptr
15861599 | 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
15871618 | }
15881619 = ok
15891620
845845 | ld y, 0
846846 | copy ^buf, ptr
847847 | copy [ptr] + y, foo
848 | copy [ptr] + y, a
848 | ld a, [ptr] + y
849849 | }
850850 = $080D LDY #$00
851851 = $080F LDA #$1F