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.ast import Program, Routine, Block, Instr
from sixtypical.model import ( from sixtypical.model import (
TYPE_BYTE, TYPE_BYTE_TABLE, BufferType, PointerType, VectorType, ExecutableType, 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 REG_A, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
) )
@ -294,7 +294,13 @@ class Analyzer(object):
elif opcode == 'copy': elif opcode == 'copy':
# check that their types are compatible # 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 pass
elif isinstance(src.type, ExecutableType) and \ elif isinstance(src.type, ExecutableType) and \
isinstance(dest.type, VectorType): isinstance(dest.type, VectorType):
@ -316,20 +322,14 @@ class Analyzer(object):
if not (src.type.trashes <= dest.type.trashes): if not (src.type.trashes <= dest.type.trashes):
raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes) raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes)
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:
context.assert_meaningful(src) context.assert_meaningful(src)
context.set_written(dest) 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
else:
raise TypeMismatchError((src, dest))
context.assert_meaningful(src, REG_Y)
context.set_written(dest)
context.set_touched(REG_A, FLAG_Z, FLAG_N) context.set_touched(REG_A, FLAG_Z, FLAG_N)
context.set_unmeaningful(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.ast import Program, Routine, Block, Instr
from sixtypical.model import ( from sixtypical.model import (
ConstantRef, ConstantRef, IndirectRef,
TYPE_BIT, TYPE_BYTE, TYPE_WORD, BufferType, PointerType, RoutineType, VectorType, TYPE_BIT, TYPE_BYTE, TYPE_WORD, BufferType, PointerType, RoutineType, VectorType,
REG_A, REG_X, REG_Y, FLAG_C REG_A, REG_X, REG_Y, FLAG_C
) )
@ -274,7 +274,17 @@ class Compiler(object):
self.compile_block(instr.block) self.compile_block(instr.block)
self.emitter.emit(CLI()) self.emitter.emit(CLI())
elif opcode == 'copy': 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): if isinstance(src, ConstantRef):
raise NotImplementedError raise NotImplementedError
else: else:
@ -322,15 +332,5 @@ class Compiler(object):
self.emitter.emit(STA(Absolute(Offset(dest_label, 1)))) self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
else: else:
raise NotImplementedError(src.type) 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: else:
raise NotImplementedError(opcode) raise NotImplementedError(opcode)

View File

@ -2,7 +2,7 @@
from sixtypical.ast import Program, Routine, Block, Instr from sixtypical.ast import Program, Routine, Block, Instr
from sixtypical.model import ( 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 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: while context.get(src) == 0:
self.eval_block(instr.block, context) self.eval_block(instr.block, context)
elif opcode == 'copy': elif opcode == 'copy':
context.set(dest, context.get(src)) if isinstance(src, IndirectRef):
# these are trashed; so could be anything really raise NotImplementedError("this doesn't actually work")
context.set(REG_A, 0) src = src.ref
context.set(FLAG_Z, 0) if isinstance(dest, IndirectRef):
context.set(FLAG_N, 0) raise NotImplementedError("this doesn't actually work")
elif opcode == 'copy[]': dest = dest.ref
addr = context.get(dest)
# memloc = memory[addr + context.get(REG_Y)]
# context.set(memloc, context.get(src))
context.set(dest, context.get(src)) context.set(dest, context.get(src))
# these are trashed; so could be anything really # these are trashed; so could be anything really
context.set(REG_A, 0) 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 # but because we store the type in here and we want to treat
# these objects as immutable, we compare the types, too. # these objects as immutable, we compare the types, too.
# Not sure if very wise. # 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 other.name == self.name and other.type == self.type
) )
@ -101,6 +101,27 @@ class LocationRef(Ref):
return isinstance(self.type, RoutineType) 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): class PartRef(Ref):
"""For 'low byte of' location and 'high byte of' location modifiers. """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 ( from sixtypical.model import (
TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE, TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE,
RoutineType, VectorType, ExecutableType, BufferType, PointerType, RoutineType, VectorType, ExecutableType, BufferType, PointerType,
LocationRef, ConstantRef LocationRef, ConstantRef, IndirectRef,
) )
from sixtypical.scanner import Scanner from sixtypical.scanner import Scanner
@ -164,6 +164,16 @@ class Parser(object):
self.scanner.scan() self.scanner.scan()
return loc 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): def block(self):
instrs = [] instrs = []
self.scanner.expect('{') self.scanner.expect('{')
@ -234,19 +244,10 @@ class Parser(object):
elif self.scanner.token in ("copy",): elif self.scanner.token in ("copy",):
opcode = self.scanner.token opcode = self.scanner.token
self.scanner.scan() self.scanner.scan()
src = self.locexpr() src = self.indlocexpr()
self.scanner.expect(',') self.scanner.expect(',')
if self.scanner.consume('['): dest = self.indlocexpr()
dest = self.locexpr() return Instr(opcode=opcode, dest=dest, src=src)
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
elif self.scanner.consume("with"): elif self.scanner.consume("with"):
self.scanner.expect("interrupts") self.scanner.expect("interrupts")
self.scanner.expect("off") self.scanner.expect("off")