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:
parent
19a196f765
commit
a95cbb0f47
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user