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.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)
|
||||||
|
|
||||||
context.assert_meaningful(src)
|
if isinstance(dest, IndirectRef):
|
||||||
context.set_written(dest)
|
context.assert_meaningful(src, REG_Y)
|
||||||
context.set_touched(REG_A, FLAG_Z, FLAG_N)
|
# TODO this will need to be more sophisticated. it's the thing ref points to that is written, not ref itself.
|
||||||
context.set_unmeaningful(REG_A, FLAG_Z, FLAG_N)
|
context.set_written(dest.ref)
|
||||||
|
|
||||||
elif opcode == 'copy[]+y':
|
|
||||||
# check that their types are compatible
|
|
||||||
if src.type == TYPE_BYTE and isinstance(dest.type, PointerType):
|
|
||||||
pass
|
|
||||||
else:
|
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_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)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user