git @ Cat's Eye Technologies SixtyPical / a95cbb0
Introduce IndirectRef and use it instead of adhoc 'copy[]+y' opcode. Chris Pressey 4 years ago
5 changed file(s) with 70 addition(s) and 51 deletion(s). Raw diff Collapse all Expand all
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
44 TYPE_BYTE, TYPE_BYTE_TABLE, BufferType, PointerType, VectorType, ExecutableType,
5 ConstantRef, LocationRef,
5 ConstantRef, LocationRef, IndirectRef,
66 REG_A, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
77 )
88
293293
294294 elif opcode == 'copy':
295295 # check that their types are compatible
296 if src.type == dest.type:
296
297 if isinstance(dest, IndirectRef):
298 if src.type == TYPE_BYTE and isinstance(dest.ref.type, PointerType):
299 pass
300 else:
301 raise TypeMismatchError((src, dest))
302 elif src.type == dest.type:
297303 pass
298304 elif isinstance(src.type, ExecutableType) and \
299305 isinstance(dest.type, VectorType):
315321 if not (src.type.trashes <= dest.type.trashes):
316322 raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes)
317323
318 context.assert_meaningful(src)
319 context.set_written(dest)
320 context.set_touched(REG_A, FLAG_Z, FLAG_N)
321 context.set_unmeaningful(REG_A, FLAG_Z, FLAG_N)
322
323 elif opcode == 'copy[]+y':
324 # check that their types are compatible
325 if src.type == TYPE_BYTE and isinstance(dest.type, PointerType):
326 pass
324 if isinstance(dest, IndirectRef):
325 context.assert_meaningful(src, REG_Y)
326 # TODO this will need to be more sophisticated. it's the thing ref points to that is written, not ref itself.
327 context.set_written(dest.ref)
327328 else:
328 raise TypeMismatchError((src, dest))
329
330 context.assert_meaningful(src, REG_Y)
331 context.set_written(dest)
329 context.assert_meaningful(src)
330 context.set_written(dest)
331
332332 context.set_touched(REG_A, FLAG_Z, FLAG_N)
333333 context.set_unmeaningful(REG_A, FLAG_Z, FLAG_N)
334334
11
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
4 ConstantRef,
4 ConstantRef, IndirectRef,
55 TYPE_BIT, TYPE_BYTE, TYPE_WORD, BufferType, PointerType, RoutineType, VectorType,
66 REG_A, REG_X, REG_Y, FLAG_C
77 )
273273 self.compile_block(instr.block)
274274 self.emitter.emit(CLI())
275275 elif opcode == 'copy':
276 if src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
276 if isinstance(dest, IndirectRef):
277 if src.type == TYPE_BYTE and isinstance(dest.ref.type, PointerType):
278 if isinstance(src, ConstantRef):
279 dest_label = self.labels[dest.ref.name]
280 self.emitter.emit(LDA(Immediate(Byte(src.value))))
281 self.emitter.emit(STA(IndirectY(dest_label)))
282 else:
283 raise NotImplementedError((src, dest))
284 else:
285 raise NotImplementedError((src, dest))
286 elif src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
277287 if isinstance(src, ConstantRef):
278288 raise NotImplementedError
279289 else:
321331 self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
322332 else:
323333 raise NotImplementedError(src.type)
324 elif opcode == 'copy[]+y':
325 if src.type == TYPE_BYTE and isinstance(dest.type, PointerType):
326 if isinstance(src, ConstantRef):
327 dest_label = self.labels[dest.name]
328 self.emitter.emit(LDA(Immediate(Byte(src.value))))
329 self.emitter.emit(STA(IndirectY(dest_label)))
330 else:
331 raise NotImplementedError((src.type, dest.type))
332 else:
333 raise NotImplementedError((src.type, dest.type))
334334 else:
335335 raise NotImplementedError(opcode)
11
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
4 ConstantRef, LocationRef, PartRef,
4 ConstantRef, LocationRef, PartRef, IndirectRef,
55 REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
66 )
77
190190 while context.get(src) == 0:
191191 self.eval_block(instr.block, context)
192192 elif opcode == 'copy':
193 context.set(dest, context.get(src))
194 # these are trashed; so could be anything really
195 context.set(REG_A, 0)
196 context.set(FLAG_Z, 0)
197 context.set(FLAG_N, 0)
198 elif opcode == 'copy[]':
199 addr = context.get(dest)
200 # memloc = memory[addr + context.get(REG_Y)]
201 # context.set(memloc, context.get(src))
193 if isinstance(src, IndirectRef):
194 raise NotImplementedError("this doesn't actually work")
195 src = src.ref
196 if isinstance(dest, IndirectRef):
197 raise NotImplementedError("this doesn't actually work")
198 dest = dest.ref
202199 context.set(dest, context.get(src))
203200 # these are trashed; so could be anything really
204201 context.set(REG_A, 0)
8686 # but because we store the type in here and we want to treat
8787 # these objects as immutable, we compare the types, too.
8888 # Not sure if very wise.
89 return isinstance(other, LocationRef) and (
89 return isinstance(other, self.__class__) and (
9090 other.name == self.name and other.type == self.type
9191 )
9292
9898
9999 def is_constant(self):
100100 return isinstance(self.type, RoutineType)
101
102
103 class IndirectRef(Ref):
104 def __init__(self, ref):
105 self.ref = ref
106
107 def __eq__(self, other):
108 return self.ref == other.ref
109
110 def __hash__(self):
111 return hash(hash('[]') ^ hash(self.ref))
112
113 def __repr__(self):
114 return '%s(%r)' % (self.__class__.__name__, self.ref)
115
116 @property
117 def name(self):
118 return '[{}]+y'.format(self.ref.name)
119
120 def is_constant(self):
121 return False
101122
102123
103124 class PartRef(Ref):
33 from sixtypical.model import (
44 TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE,
55 RoutineType, VectorType, ExecutableType, BufferType, PointerType,
6 LocationRef, ConstantRef
6 LocationRef, ConstantRef, IndirectRef,
77 )
88 from sixtypical.scanner import Scanner
99
162162 loc = self.lookup(self.scanner.token)
163163 self.scanner.scan()
164164 return loc
165
166 def indlocexpr(self):
167 if self.scanner.consume('['):
168 loc = self.locexpr()
169 self.scanner.expect(']')
170 self.scanner.expect('+')
171 self.scanner.expect('y')
172 return IndirectRef(loc)
173 else:
174 return self.locexpr()
165175
166176 def block(self):
167177 instrs = []
233243 elif self.scanner.token in ("copy",):
234244 opcode = self.scanner.token
235245 self.scanner.scan()
236 src = self.locexpr()
246 src = self.indlocexpr()
237247 self.scanner.expect(',')
238 if self.scanner.consume('['):
239 dest = self.locexpr()
240 self.scanner.expect(']')
241 self.scanner.expect('+')
242 self.scanner.expect('y')
243 opcode = 'copy[]+y'
244 else:
245 dest = self.locexpr()
246 i = Instr(opcode=opcode, dest=dest, src=src)
247 #print repr(i)
248 return i
248 dest = self.indlocexpr()
249 return Instr(opcode=opcode, dest=dest, src=src)
249250 elif self.scanner.consume("with"):
250251 self.scanner.expect("interrupts")
251252 self.scanner.expect("off")