2015-10-16 22:12:52 +00:00
|
|
|
# encoding: UTF-8
|
|
|
|
|
|
|
|
from sixtypical.ast import Program, Routine, Block, Instr
|
|
|
|
from sixtypical.model import (
|
2017-12-08 15:53:18 +00:00
|
|
|
ConstantRef, LocationRef, IndexedRef, IndirectRef, AddressRef,
|
|
|
|
TYPE_BIT, TYPE_BYTE, TYPE_WORD, TYPE_WORD_TABLE, BufferType, PointerType, RoutineType, VectorType,
|
2015-10-20 08:33:30 +00:00
|
|
|
REG_A, REG_X, REG_Y, FLAG_C
|
2015-10-16 22:12:52 +00:00
|
|
|
)
|
2015-10-22 15:20:10 +00:00
|
|
|
from sixtypical.emitter import Byte, Label, Offset, LowAddressByte, HighAddressByte
|
2015-10-17 10:08:25 +00:00
|
|
|
from sixtypical.gen6502 import (
|
2017-11-24 13:09:10 +00:00
|
|
|
Immediate, Absolute, AbsoluteX, AbsoluteY, ZeroPage, Indirect, IndirectY, Relative,
|
2015-10-17 15:17:35 +00:00
|
|
|
LDA, LDX, LDY, STA, STX, STY,
|
2015-10-18 12:55:40 +00:00
|
|
|
TAX, TAY, TXA, TYA,
|
2015-10-17 15:17:35 +00:00
|
|
|
CLC, SEC, ADC, SBC, ROL, ROR,
|
2015-10-17 14:46:28 +00:00
|
|
|
INC, INX, INY, DEC, DEX, DEY,
|
2015-10-17 15:17:35 +00:00
|
|
|
CMP, CPX, CPY, AND, ORA, EOR,
|
2015-10-18 12:55:40 +00:00
|
|
|
BCC, BCS, BNE, BEQ,
|
2015-10-17 15:34:02 +00:00
|
|
|
JMP, JSR, RTS,
|
2015-10-18 22:15:40 +00:00
|
|
|
SEI, CLI,
|
2015-10-17 10:08:25 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class UnsupportedOpcodeError(KeyError):
|
|
|
|
pass
|
2015-10-16 22:12:52 +00:00
|
|
|
|
|
|
|
|
2015-10-17 14:06:50 +00:00
|
|
|
class Compiler(object):
|
|
|
|
def __init__(self, emitter):
|
|
|
|
self.emitter = emitter
|
|
|
|
self.routines = {}
|
|
|
|
self.labels = {}
|
2015-10-22 14:45:16 +00:00
|
|
|
self.trampolines = {} # Location -> Label
|
2015-10-16 22:12:52 +00:00
|
|
|
|
2015-10-17 14:06:50 +00:00
|
|
|
def compile_program(self, program):
|
|
|
|
assert isinstance(program, Program)
|
2015-10-17 14:46:28 +00:00
|
|
|
|
|
|
|
for defn in program.defns:
|
|
|
|
label = Label(defn.name)
|
2015-10-18 15:22:36 +00:00
|
|
|
if defn.addr is not None:
|
|
|
|
label.set_addr(defn.addr)
|
2015-10-17 14:46:28 +00:00
|
|
|
self.labels[defn.name] = label
|
|
|
|
|
2015-10-17 14:06:50 +00:00
|
|
|
for routine in program.routines:
|
|
|
|
self.routines[routine.name] = routine
|
|
|
|
label = Label(routine.name)
|
|
|
|
if routine.addr is not None:
|
|
|
|
label.set_addr(routine.addr)
|
|
|
|
self.labels[routine.name] = label
|
2015-10-17 14:23:00 +00:00
|
|
|
|
|
|
|
self.compile_routine(self.routines['main'])
|
2015-10-17 14:06:50 +00:00
|
|
|
for routine in program.routines:
|
2015-10-17 14:23:00 +00:00
|
|
|
if routine.name != 'main':
|
|
|
|
self.compile_routine(routine)
|
2015-10-16 22:12:52 +00:00
|
|
|
|
2015-10-22 14:45:16 +00:00
|
|
|
for location, label in self.trampolines.iteritems():
|
|
|
|
self.emitter.resolve_label(label)
|
|
|
|
self.emitter.emit(JMP(Indirect(self.labels[location.name])))
|
|
|
|
|
2016-06-16 16:03:31 +00:00
|
|
|
# initialized data
|
2015-10-17 14:46:28 +00:00
|
|
|
for defn in program.defns:
|
2016-06-16 16:03:31 +00:00
|
|
|
if defn.initial is not None:
|
|
|
|
label = self.labels[defn.name]
|
|
|
|
self.emitter.resolve_label(label)
|
|
|
|
self.emitter.emit(Byte(defn.initial))
|
|
|
|
|
|
|
|
# uninitialized, "BSS" data
|
|
|
|
for defn in program.defns:
|
|
|
|
if defn.initial is None and defn.addr is None:
|
2015-10-18 15:22:36 +00:00
|
|
|
label = self.labels[defn.name]
|
|
|
|
self.emitter.resolve_bss_label(label)
|
2015-10-17 14:46:28 +00:00
|
|
|
|
2015-10-22 14:45:16 +00:00
|
|
|
|
2015-10-17 14:06:50 +00:00
|
|
|
def compile_routine(self, routine):
|
|
|
|
assert isinstance(routine, Routine)
|
|
|
|
if routine.block:
|
2015-10-17 14:23:00 +00:00
|
|
|
self.emitter.resolve_label(self.labels[routine.name])
|
2015-10-17 14:06:50 +00:00
|
|
|
self.compile_block(routine.block)
|
|
|
|
self.emitter.emit(RTS())
|
2015-10-16 22:12:52 +00:00
|
|
|
|
2015-10-17 14:06:50 +00:00
|
|
|
def compile_block(self, block):
|
|
|
|
assert isinstance(block, Block)
|
|
|
|
for instr in block.instrs:
|
|
|
|
self.compile_instr(instr)
|
2015-10-16 22:12:52 +00:00
|
|
|
|
2015-10-17 14:06:50 +00:00
|
|
|
def compile_instr(self, instr):
|
|
|
|
assert isinstance(instr, Instr)
|
|
|
|
opcode = instr.opcode
|
|
|
|
dest = instr.dest
|
|
|
|
src = instr.src
|
|
|
|
|
|
|
|
if opcode == 'ld':
|
|
|
|
if dest == REG_A:
|
2015-10-18 12:55:40 +00:00
|
|
|
if src == REG_X:
|
|
|
|
self.emitter.emit(TXA())
|
|
|
|
elif src == REG_Y:
|
|
|
|
self.emitter.emit(TYA())
|
|
|
|
elif isinstance(src, ConstantRef):
|
2015-10-17 14:06:50 +00:00
|
|
|
self.emitter.emit(LDA(Immediate(Byte(src.value))))
|
2015-10-18 17:32:20 +00:00
|
|
|
elif instr.index == REG_X:
|
|
|
|
self.emitter.emit(LDA(AbsoluteX(self.labels[src.name])))
|
|
|
|
elif instr.index == REG_Y:
|
|
|
|
self.emitter.emit(LDA(AbsoluteY(self.labels[src.name])))
|
2015-10-17 14:06:50 +00:00
|
|
|
else:
|
2015-10-17 14:23:00 +00:00
|
|
|
self.emitter.emit(LDA(Absolute(self.labels[src.name])))
|
2015-10-17 14:06:50 +00:00
|
|
|
elif dest == REG_X:
|
2015-10-18 12:55:40 +00:00
|
|
|
if src == REG_A:
|
|
|
|
self.emitter.emit(TAX())
|
|
|
|
elif isinstance(src, ConstantRef):
|
2015-10-17 14:23:00 +00:00
|
|
|
self.emitter.emit(LDX(Immediate(Byte(src.value))))
|
2015-10-18 17:32:20 +00:00
|
|
|
elif instr.index == REG_Y:
|
|
|
|
self.emitter.emit(LDX(AbsoluteY(self.labels[src.name])))
|
2015-10-17 14:23:00 +00:00
|
|
|
else:
|
|
|
|
self.emitter.emit(LDX(Absolute(self.labels[src.name])))
|
2015-10-17 14:06:50 +00:00
|
|
|
elif dest == REG_Y:
|
2015-10-18 12:55:40 +00:00
|
|
|
if src == REG_A:
|
|
|
|
self.emitter.emit(TAY())
|
|
|
|
elif isinstance(src, ConstantRef):
|
2015-10-17 14:23:00 +00:00
|
|
|
self.emitter.emit(LDY(Immediate(Byte(src.value))))
|
2015-10-18 17:32:20 +00:00
|
|
|
elif instr.index == REG_X:
|
|
|
|
self.emitter.emit(LDY(AbsoluteX(self.labels[src.name])))
|
2015-10-17 14:23:00 +00:00
|
|
|
else:
|
|
|
|
self.emitter.emit(LDY(Absolute(self.labels[src.name])))
|
2015-10-17 09:17:44 +00:00
|
|
|
else:
|
2015-10-17 14:06:50 +00:00
|
|
|
raise UnsupportedOpcodeError(instr)
|
|
|
|
elif opcode == 'st':
|
2015-10-18 16:23:01 +00:00
|
|
|
if dest == FLAG_C and src == ConstantRef(TYPE_BIT, 0):
|
2015-10-17 14:06:50 +00:00
|
|
|
self.emitter.emit(CLC())
|
2015-10-18 16:23:01 +00:00
|
|
|
elif dest == FLAG_C and src == ConstantRef(TYPE_BIT, 1):
|
2015-10-17 14:06:50 +00:00
|
|
|
self.emitter.emit(SEC())
|
|
|
|
else:
|
2015-10-18 17:32:20 +00:00
|
|
|
op_cls = {
|
|
|
|
REG_A: STA,
|
|
|
|
REG_X: STX,
|
|
|
|
REG_Y: STY
|
|
|
|
}.get(src, None)
|
|
|
|
mode_cls = {
|
|
|
|
REG_X: AbsoluteX,
|
|
|
|
REG_Y: AbsoluteY,
|
|
|
|
None: Absolute
|
|
|
|
}.get(instr.index, None)
|
|
|
|
if op_cls is None or mode_cls is None:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
|
|
|
self.emitter.emit(op_cls(mode_cls(self.labels[dest.name])))
|
2015-10-17 14:06:50 +00:00
|
|
|
elif opcode == 'add':
|
|
|
|
if dest == REG_A:
|
|
|
|
if isinstance(src, ConstantRef):
|
|
|
|
self.emitter.emit(ADC(Immediate(Byte(src.value))))
|
|
|
|
else:
|
2015-10-17 14:46:28 +00:00
|
|
|
self.emitter.emit(ADC(Absolute(self.labels[src.name])))
|
2017-12-07 14:14:43 +00:00
|
|
|
elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD:
|
2017-12-07 13:15:21 +00:00
|
|
|
if isinstance(src, ConstantRef):
|
|
|
|
dest_label = self.labels[dest.name]
|
|
|
|
self.emitter.emit(LDA(Absolute(dest_label)))
|
|
|
|
self.emitter.emit(ADC(Immediate(Byte(src.low_byte()))))
|
|
|
|
self.emitter.emit(STA(Absolute(dest_label)))
|
|
|
|
self.emitter.emit(LDA(Absolute(Offset(dest_label, 1))))
|
|
|
|
self.emitter.emit(ADC(Immediate(Byte(src.high_byte()))))
|
|
|
|
self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
|
|
|
|
elif isinstance(src, LocationRef):
|
|
|
|
src_label = self.labels[src.name]
|
|
|
|
dest_label = self.labels[dest.name]
|
|
|
|
self.emitter.emit(LDA(Absolute(dest_label)))
|
|
|
|
self.emitter.emit(ADC(Absolute(src_label)))
|
|
|
|
self.emitter.emit(STA(Absolute(dest_label)))
|
|
|
|
self.emitter.emit(LDA(Absolute(Offset(dest_label, 1))))
|
|
|
|
self.emitter.emit(ADC(Absolute(Offset(src_label, 1))))
|
|
|
|
self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
|
|
|
|
else:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
2017-12-07 14:14:43 +00:00
|
|
|
elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and isinstance(dest.type, PointerType):
|
|
|
|
if isinstance(src, ConstantRef):
|
2017-12-08 15:53:18 +00:00
|
|
|
dest_label = self.labels[dest.name]
|
2017-12-07 14:14:43 +00:00
|
|
|
self.emitter.emit(LDA(ZeroPage(dest_label)))
|
|
|
|
self.emitter.emit(ADC(Immediate(Byte(src.low_byte()))))
|
|
|
|
self.emitter.emit(STA(ZeroPage(dest_label)))
|
|
|
|
self.emitter.emit(LDA(ZeroPage(Offset(dest_label, 1))))
|
|
|
|
self.emitter.emit(ADC(Immediate(Byte(src.high_byte()))))
|
|
|
|
self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
|
|
|
|
elif isinstance(src, LocationRef):
|
|
|
|
src_label = self.labels[src.name]
|
2017-12-08 15:53:18 +00:00
|
|
|
dest_label = self.labels[dest.name]
|
2017-12-07 14:14:43 +00:00
|
|
|
self.emitter.emit(LDA(ZeroPage(dest_label)))
|
|
|
|
self.emitter.emit(ADC(Absolute(src_label)))
|
|
|
|
self.emitter.emit(STA(ZeroPage(dest_label)))
|
|
|
|
self.emitter.emit(LDA(ZeroPage(Offset(dest_label, 1))))
|
|
|
|
self.emitter.emit(ADC(Absolute(Offset(src_label, 1))))
|
|
|
|
self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
|
|
|
|
else:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
2015-10-17 10:08:25 +00:00
|
|
|
else:
|
2015-10-17 14:06:50 +00:00
|
|
|
raise UnsupportedOpcodeError(instr)
|
|
|
|
elif opcode == 'sub':
|
2015-10-17 14:46:28 +00:00
|
|
|
if dest == REG_A:
|
|
|
|
if isinstance(src, ConstantRef):
|
|
|
|
self.emitter.emit(SBC(Immediate(Byte(src.value))))
|
|
|
|
else:
|
|
|
|
self.emitter.emit(SBC(Absolute(self.labels[src.name])))
|
|
|
|
else:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
2015-10-17 14:06:50 +00:00
|
|
|
elif opcode == 'inc':
|
2015-10-17 14:46:28 +00:00
|
|
|
if dest == REG_X:
|
|
|
|
self.emitter.emit(INX())
|
|
|
|
elif dest == REG_Y:
|
|
|
|
self.emitter.emit(INY())
|
|
|
|
else:
|
|
|
|
self.emitter.emit(INC(Absolute(self.labels[dest.name])))
|
2015-10-17 14:06:50 +00:00
|
|
|
elif opcode == 'dec':
|
2015-10-17 14:46:28 +00:00
|
|
|
if dest == REG_X:
|
|
|
|
self.emitter.emit(DEX())
|
|
|
|
elif dest == REG_Y:
|
|
|
|
self.emitter.emit(DEY())
|
|
|
|
else:
|
|
|
|
self.emitter.emit(DEC(Absolute(self.labels[dest.name])))
|
2015-10-17 14:06:50 +00:00
|
|
|
elif opcode == 'cmp':
|
2015-10-17 15:17:35 +00:00
|
|
|
cls = {
|
|
|
|
'a': CMP,
|
|
|
|
'x': CPX,
|
|
|
|
'y': CPY,
|
|
|
|
}.get(dest.name)
|
|
|
|
if cls is None:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
|
|
|
if isinstance(src, ConstantRef):
|
|
|
|
self.emitter.emit(cls(Immediate(Byte(src.value))))
|
|
|
|
else:
|
|
|
|
self.emitter.emit(cls(Absolute(self.labels[src.name])))
|
|
|
|
elif opcode in ('and', 'or', 'xor',):
|
|
|
|
cls = {
|
|
|
|
'and': AND,
|
|
|
|
'or': ORA,
|
|
|
|
'xor': EOR,
|
|
|
|
}[opcode]
|
|
|
|
if dest == REG_A:
|
|
|
|
if isinstance(src, ConstantRef):
|
|
|
|
self.emitter.emit(cls(Immediate(Byte(src.value))))
|
|
|
|
else:
|
|
|
|
self.emitter.emit(cls(Absolute(self.labels[src.name])))
|
|
|
|
else:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
|
|
|
elif opcode in ('shl', 'shr'):
|
|
|
|
cls = {
|
|
|
|
'shl': ROL,
|
|
|
|
'shr': ROR,
|
|
|
|
}[opcode]
|
|
|
|
if dest == REG_A:
|
|
|
|
self.emitter.emit(cls())
|
|
|
|
else:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
2015-10-17 14:06:50 +00:00
|
|
|
elif opcode == 'call':
|
2015-10-20 12:15:21 +00:00
|
|
|
location = instr.location
|
2015-10-20 11:53:07 +00:00
|
|
|
label = self.labels[instr.location.name]
|
2015-10-20 12:15:21 +00:00
|
|
|
if isinstance(location.type, RoutineType):
|
|
|
|
self.emitter.emit(JSR(Absolute(label)))
|
|
|
|
elif isinstance(location.type, VectorType):
|
2015-10-22 14:45:16 +00:00
|
|
|
trampoline = self.trampolines.setdefault(
|
|
|
|
location, Label(location.name + '_trampoline')
|
|
|
|
)
|
|
|
|
self.emitter.emit(JSR(Absolute(trampoline)))
|
2015-10-20 12:15:21 +00:00
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
2015-10-21 14:51:52 +00:00
|
|
|
elif opcode == 'goto':
|
|
|
|
location = instr.location
|
|
|
|
label = self.labels[instr.location.name]
|
|
|
|
if isinstance(location.type, RoutineType):
|
|
|
|
self.emitter.emit(JMP(Absolute(label)))
|
|
|
|
elif isinstance(location.type, VectorType):
|
|
|
|
self.emitter.emit(JMP(Indirect(label)))
|
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
2015-10-17 14:06:50 +00:00
|
|
|
elif opcode == 'if':
|
2015-10-17 15:34:02 +00:00
|
|
|
cls = {
|
2015-10-18 14:32:28 +00:00
|
|
|
False: {
|
|
|
|
'c': BCC,
|
|
|
|
'z': BNE,
|
|
|
|
},
|
|
|
|
True: {
|
|
|
|
'c': BCS,
|
|
|
|
'z': BEQ,
|
|
|
|
},
|
|
|
|
}[instr.inverted].get(src.name)
|
2015-10-17 15:34:02 +00:00
|
|
|
if cls is None:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
|
|
|
else_label = Label('else_label')
|
|
|
|
self.emitter.emit(cls(Relative(else_label)))
|
|
|
|
self.compile_block(instr.block1)
|
2015-10-17 17:25:54 +00:00
|
|
|
if instr.block2 is not None:
|
2015-10-17 15:34:02 +00:00
|
|
|
end_label = Label('end_label')
|
|
|
|
self.emitter.emit(JMP(Absolute(end_label)))
|
|
|
|
self.emitter.resolve_label(else_label)
|
|
|
|
self.compile_block(instr.block2)
|
|
|
|
self.emitter.resolve_label(end_label)
|
|
|
|
else:
|
|
|
|
self.emitter.resolve_label(else_label)
|
2015-10-18 12:55:40 +00:00
|
|
|
elif opcode == 'repeat':
|
|
|
|
top_label = self.emitter.make_label()
|
|
|
|
self.compile_block(instr.block)
|
2015-10-18 14:32:28 +00:00
|
|
|
if src is None:
|
|
|
|
self.emitter.emit(JMP(Absolute(top_label)))
|
|
|
|
else:
|
|
|
|
cls = {
|
|
|
|
False: {
|
|
|
|
'c': BCC,
|
|
|
|
'z': BNE,
|
|
|
|
},
|
|
|
|
True: {
|
|
|
|
'c': BCS,
|
|
|
|
'z': BEQ,
|
|
|
|
},
|
|
|
|
}[instr.inverted].get(src.name)
|
|
|
|
if cls is None:
|
|
|
|
raise UnsupportedOpcodeError(instr)
|
|
|
|
self.emitter.emit(cls(Relative(top_label)))
|
2015-10-18 22:15:40 +00:00
|
|
|
elif opcode == 'with-sei':
|
|
|
|
self.emitter.emit(SEI())
|
|
|
|
self.compile_block(instr.block)
|
|
|
|
self.emitter.emit(CLI())
|
2015-10-18 22:31:17 +00:00
|
|
|
elif opcode == 'copy':
|
2017-12-01 13:52:56 +00:00
|
|
|
if isinstance(src, (LocationRef, ConstantRef)) and isinstance(dest, IndirectRef):
|
2017-12-01 11:44:40 +00:00
|
|
|
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)))
|
2017-12-01 13:52:56 +00:00
|
|
|
elif isinstance(src, LocationRef):
|
|
|
|
src_label = self.labels[src.name]
|
|
|
|
dest_label = self.labels[dest.ref.name]
|
|
|
|
self.emitter.emit(LDA(Absolute(src_label)))
|
|
|
|
self.emitter.emit(STA(IndirectY(dest_label)))
|
2017-12-01 11:44:40 +00:00
|
|
|
else:
|
|
|
|
raise NotImplementedError((src, dest))
|
|
|
|
else:
|
|
|
|
raise NotImplementedError((src, dest))
|
2017-12-01 13:52:56 +00:00
|
|
|
elif isinstance(src, IndirectRef) and isinstance(dest, LocationRef):
|
|
|
|
if dest.type == TYPE_BYTE and isinstance(src.ref.type, PointerType):
|
|
|
|
src_label = self.labels[src.ref.name]
|
|
|
|
dest_label = self.labels[dest.name]
|
|
|
|
self.emitter.emit(LDA(IndirectY(src_label)))
|
|
|
|
self.emitter.emit(STA(Absolute(dest_label)))
|
|
|
|
else:
|
|
|
|
raise NotImplementedError((src, dest))
|
2017-12-01 12:36:58 +00:00
|
|
|
elif isinstance(src, AddressRef) and isinstance(dest, LocationRef) and \
|
|
|
|
isinstance(src.ref.type, BufferType) and isinstance(dest.type, PointerType):
|
|
|
|
src_label = self.labels[src.ref.name]
|
|
|
|
dest_label = self.labels[dest.name]
|
|
|
|
self.emitter.emit(LDA(Immediate(HighAddressByte(src_label))))
|
|
|
|
self.emitter.emit(STA(ZeroPage(dest_label)))
|
|
|
|
self.emitter.emit(LDA(Immediate(LowAddressByte(src_label))))
|
|
|
|
self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
|
2017-12-08 15:53:18 +00:00
|
|
|
elif isinstance(src, LocationRef) and isinstance(dest, IndexedRef):
|
|
|
|
if src.type == TYPE_WORD and dest.ref.type == TYPE_WORD_TABLE:
|
|
|
|
src_label = self.labels[src.name]
|
|
|
|
dest_label = self.labels[dest.ref.name]
|
|
|
|
raise NotImplementedError("""\
|
|
|
|
What we will need to do here, is to have TWO 'labels' per name, one for the high byte table,
|
|
|
|
and one for the low byte table. Then select AbsoluteX() or AbsoluteY() addressing on those
|
|
|
|
tables. And use that in the STA() part.""")
|
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
|
|
|
|
2017-12-01 12:36:58 +00:00
|
|
|
elif not isinstance(src, (ConstantRef, LocationRef)) or not isinstance(dest, LocationRef):
|
|
|
|
raise NotImplementedError((src, dest))
|
2017-12-01 11:44:40 +00:00
|
|
|
elif src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
|
2017-11-20 15:18:21 +00:00
|
|
|
if isinstance(src, ConstantRef):
|
|
|
|
raise NotImplementedError
|
|
|
|
else:
|
|
|
|
src_label = self.labels[src.name]
|
|
|
|
dest_label = self.labels[dest.name]
|
|
|
|
self.emitter.emit(LDA(Absolute(src_label)))
|
|
|
|
self.emitter.emit(STA(Absolute(dest_label)))
|
2016-06-16 16:10:03 +00:00
|
|
|
elif src.type == TYPE_WORD and dest.type == TYPE_WORD:
|
2017-11-20 15:18:21 +00:00
|
|
|
if isinstance(src, ConstantRef):
|
|
|
|
dest_label = self.labels[dest.name]
|
2017-12-07 12:48:56 +00:00
|
|
|
self.emitter.emit(LDA(Immediate(Byte(src.low_byte()))))
|
2017-12-07 16:49:43 +00:00
|
|
|
self.emitter.emit(STA(Absolute(dest_label)))
|
|
|
|
self.emitter.emit(LDA(Immediate(Byte(src.high_byte()))))
|
2017-11-20 15:18:21 +00:00
|
|
|
self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
|
|
|
|
else:
|
|
|
|
src_label = self.labels[src.name]
|
|
|
|
dest_label = self.labels[dest.name]
|
|
|
|
self.emitter.emit(LDA(Absolute(src_label)))
|
|
|
|
self.emitter.emit(STA(Absolute(dest_label)))
|
|
|
|
self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
|
|
|
|
self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
|
2016-06-16 16:10:03 +00:00
|
|
|
elif isinstance(src.type, VectorType) and isinstance(dest.type, VectorType):
|
2015-10-19 07:55:47 +00:00
|
|
|
src_label = self.labels[src.name]
|
|
|
|
dest_label = self.labels[dest.name]
|
|
|
|
self.emitter.emit(LDA(Absolute(src_label)))
|
|
|
|
self.emitter.emit(STA(Absolute(dest_label)))
|
|
|
|
self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
|
|
|
|
self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
|
2015-10-22 15:20:10 +00:00
|
|
|
elif isinstance(src.type, RoutineType) and isinstance(dest.type, VectorType):
|
|
|
|
src_label = self.labels[src.name]
|
|
|
|
dest_label = self.labels[dest.name]
|
|
|
|
self.emitter.emit(LDA(Immediate(HighAddressByte(src_label))))
|
|
|
|
self.emitter.emit(STA(Absolute(dest_label)))
|
|
|
|
self.emitter.emit(LDA(Immediate(LowAddressByte(src_label))))
|
|
|
|
self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
|
2015-10-18 22:31:17 +00:00
|
|
|
else:
|
|
|
|
raise NotImplementedError(src.type)
|
2015-10-17 10:08:25 +00:00
|
|
|
else:
|
2015-10-18 22:31:17 +00:00
|
|
|
raise NotImplementedError(opcode)
|