1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-11-26 14:49:15 +00:00

Introduce IndirectRef and use it instead of adhoc 'copy[]+y' opcode.

This commit is contained in:
Chris Pressey 2017-12-01 11:44:40 +00:00
parent 19a196f765
commit a95cbb0f47
5 changed files with 69 additions and 50 deletions

View File

@ -3,7 +3,7 @@
from sixtypical.ast import Program, Routine, Block, Instr
from sixtypical.model import (
TYPE_BYTE, TYPE_BYTE_TABLE, BufferType, PointerType, VectorType, ExecutableType,
ConstantRef, LocationRef,
ConstantRef, LocationRef, IndirectRef,
REG_A, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
)
@ -294,7 +294,13 @@ class Analyzer(object):
elif opcode == 'copy':
# check that their types are compatible
if src.type == dest.type:
if isinstance(dest, IndirectRef):
if src.type == TYPE_BYTE and isinstance(dest.ref.type, PointerType):
pass
else:
raise TypeMismatchError((src, dest))
elif src.type == dest.type:
pass
elif isinstance(src.type, ExecutableType) and \
isinstance(dest.type, VectorType):
@ -316,20 +322,14 @@ class Analyzer(object):
if not (src.type.trashes <= dest.type.trashes):
raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes)
context.assert_meaningful(src)
context.set_written(dest)
context.set_touched(REG_A, FLAG_Z, FLAG_N)
context.set_unmeaningful(REG_A, FLAG_Z, FLAG_N)
elif opcode == 'copy[]+y':
# check that their types are compatible
if src.type == TYPE_BYTE and isinstance(dest.type, PointerType):
pass
if isinstance(dest, IndirectRef):
context.assert_meaningful(src, REG_Y)
# TODO this will need to be more sophisticated. it's the thing ref points to that is written, not ref itself.
context.set_written(dest.ref)
else:
raise TypeMismatchError((src, dest))
context.assert_meaningful(src)
context.set_written(dest)
context.assert_meaningful(src, REG_Y)
context.set_written(dest)
context.set_touched(REG_A, FLAG_Z, FLAG_N)
context.set_unmeaningful(REG_A, FLAG_Z, FLAG_N)

View File

@ -2,7 +2,7 @@
from sixtypical.ast import Program, Routine, Block, Instr
from sixtypical.model import (
ConstantRef,
ConstantRef, IndirectRef,
TYPE_BIT, TYPE_BYTE, TYPE_WORD, BufferType, PointerType, RoutineType, VectorType,
REG_A, REG_X, REG_Y, FLAG_C
)
@ -274,7 +274,17 @@ class Compiler(object):
self.compile_block(instr.block)
self.emitter.emit(CLI())
elif opcode == 'copy':
if src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
if isinstance(dest, IndirectRef):
if src.type == TYPE_BYTE and isinstance(dest.ref.type, PointerType):
if isinstance(src, ConstantRef):
dest_label = self.labels[dest.ref.name]
self.emitter.emit(LDA(Immediate(Byte(src.value))))
self.emitter.emit(STA(IndirectY(dest_label)))
else:
raise NotImplementedError((src, dest))
else:
raise NotImplementedError((src, dest))
elif src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
if isinstance(src, ConstantRef):
raise NotImplementedError
else:
@ -322,15 +332,5 @@ class Compiler(object):
self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
else:
raise NotImplementedError(src.type)
elif opcode == 'copy[]+y':
if src.type == TYPE_BYTE and isinstance(dest.type, PointerType):
if isinstance(src, ConstantRef):
dest_label = self.labels[dest.name]
self.emitter.emit(LDA(Immediate(Byte(src.value))))
self.emitter.emit(STA(IndirectY(dest_label)))
else:
raise NotImplementedError((src.type, dest.type))
else:
raise NotImplementedError((src.type, dest.type))
else:
raise NotImplementedError(opcode)

View File

@ -2,7 +2,7 @@
from sixtypical.ast import Program, Routine, Block, Instr
from sixtypical.model import (
ConstantRef, LocationRef, PartRef,
ConstantRef, LocationRef, PartRef, IndirectRef,
REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
)
@ -191,15 +191,12 @@ class Evaluator(object):
while context.get(src) == 0:
self.eval_block(instr.block, context)
elif opcode == 'copy':
context.set(dest, context.get(src))
# these are trashed; so could be anything really
context.set(REG_A, 0)
context.set(FLAG_Z, 0)
context.set(FLAG_N, 0)
elif opcode == 'copy[]':
addr = context.get(dest)
# memloc = memory[addr + context.get(REG_Y)]
# context.set(memloc, context.get(src))
if isinstance(src, IndirectRef):
raise NotImplementedError("this doesn't actually work")
src = src.ref
if isinstance(dest, IndirectRef):
raise NotImplementedError("this doesn't actually work")
dest = dest.ref
context.set(dest, context.get(src))
# these are trashed; so could be anything really
context.set(REG_A, 0)

View File

@ -87,7 +87,7 @@ class LocationRef(Ref):
# but because we store the type in here and we want to treat
# these objects as immutable, we compare the types, too.
# Not sure if very wise.
return isinstance(other, LocationRef) and (
return isinstance(other, self.__class__) and (
other.name == self.name and other.type == self.type
)
@ -101,6 +101,27 @@ class LocationRef(Ref):
return isinstance(self.type, RoutineType)
class IndirectRef(Ref):
def __init__(self, ref):
self.ref = ref
def __eq__(self, other):
return self.ref == other.ref
def __hash__(self):
return hash(hash('[]') ^ hash(self.ref))
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.ref)
@property
def name(self):
return '[{}]+y'.format(self.ref.name)
def is_constant(self):
return False
class PartRef(Ref):
"""For 'low byte of' location and 'high byte of' location modifiers.

View File

@ -4,7 +4,7 @@ from sixtypical.ast import Program, Defn, Routine, Block, Instr
from sixtypical.model import (
TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE,
RoutineType, VectorType, ExecutableType, BufferType, PointerType,
LocationRef, ConstantRef
LocationRef, ConstantRef, IndirectRef,
)
from sixtypical.scanner import Scanner
@ -164,6 +164,16 @@ class Parser(object):
self.scanner.scan()
return loc
def indlocexpr(self):
if self.scanner.consume('['):
loc = self.locexpr()
self.scanner.expect(']')
self.scanner.expect('+')
self.scanner.expect('y')
return IndirectRef(loc)
else:
return self.locexpr()
def block(self):
instrs = []
self.scanner.expect('{')
@ -234,19 +244,10 @@ class Parser(object):
elif self.scanner.token in ("copy",):
opcode = self.scanner.token
self.scanner.scan()
src = self.locexpr()
src = self.indlocexpr()
self.scanner.expect(',')
if self.scanner.consume('['):
dest = self.locexpr()
self.scanner.expect(']')
self.scanner.expect('+')
self.scanner.expect('y')
opcode = 'copy[]+y'
else:
dest = self.locexpr()
i = Instr(opcode=opcode, dest=dest, src=src)
#print repr(i)
return i
dest = self.indlocexpr()
return Instr(opcode=opcode, dest=dest, src=src)
elif self.scanner.consume("with"):
self.scanner.expect("interrupts")
self.scanner.expect("off")