1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-09-29 23:56:02 +00:00
SixtyPical/src/sixtypical/compiler.py

106 lines
3.1 KiB
Python
Raw Normal View History

2015-10-16 22:12:52 +00:00
# encoding: UTF-8
from sixtypical.ast import Program, Routine, Block, Instr
from sixtypical.model import (
ConstantRef, LocationRef,
REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
)
from sixtypical.emitter import Byte
from sixtypical.gen6502 import (
Immediate, Absolute,
LDA, LDX, LDY, STA, STX, STY, CLC, SEC, ADC, RTS
)
class UnsupportedOpcodeError(KeyError):
pass
2015-10-16 22:12:52 +00:00
def compile_program(program, emitter):
2015-10-16 22:12:52 +00:00
assert isinstance(program, Program)
routines = {r.name: r for r in program.routines}
for routine in program.routines:
compile_routine(routine, emitter, routines)
2015-10-16 22:12:52 +00:00
def compile_routine(routine, emitter, routines):
2015-10-16 22:12:52 +00:00
assert isinstance(routine, Routine)
label = emitter.make_label(routine.name)
2015-10-17 13:54:28 +00:00
if routine.block:
compile_block(routine.block, emitter, routines)
emitter.emit(RTS())
2015-10-16 22:12:52 +00:00
return label
def compile_block(block, emitter, routines):
2015-10-16 22:12:52 +00:00
assert isinstance(block, Block)
label = emitter.make_label()
2015-10-16 22:12:52 +00:00
for instr in block.instrs:
compile_instr(instr, emitter, routines)
2015-10-16 22:12:52 +00:00
return label
def compile_instr(instr, emitter, routines):
2015-10-16 22:12:52 +00:00
assert isinstance(instr, Instr)
opcode = instr.opcode
dest = instr.dest
src = instr.src
if opcode == 'ld':
if dest == REG_A:
if isinstance(src, ConstantRef):
emitter.emit(LDA(Immediate(Byte(src.value))))
else:
emitter.emit(LDA(Absolute(src.label)))
2015-10-16 22:12:52 +00:00
elif dest == REG_X:
pass
2015-10-16 22:12:52 +00:00
elif dest == REG_Y:
pass
2015-10-16 22:12:52 +00:00
else:
raise UnsupportedOpcodeError(instr)
2015-10-16 22:12:52 +00:00
elif opcode == 'st':
if dest == FLAG_C and src == ConstantRef(0):
emitter.emit(CLC())
elif dest == FLAG_C and src == ConstantRef(1):
emitter.emit(SEC())
elif src == REG_A:
emitter.emit(STA(Absolute(dest.label)))
elif src == REG_X:
emitter.emit(STX(Absolute(dest.label)))
elif src == REG_Y:
emitter.emit(STY(Absolute(dest.label)))
2015-10-16 22:12:52 +00:00
else:
raise UnsupportedOpcodeError(instr)
2015-10-16 22:12:52 +00:00
elif opcode == 'add':
if dest == REG_A:
if isinstance(src, ConstantRef):
emitter.emit(ADC(Immediate(Byte(src.value))))
else:
emitter.emit(ADC(Absolute(src.label)))
else:
raise UnsupportedOpcodeError(instr)
2015-10-16 22:12:52 +00:00
elif opcode == 'sub':
raise NotImplementedError
elif opcode == 'inc':
raise NotImplementedError
elif opcode == 'dec':
raise NotImplementedError
elif opcode == 'cmp':
raise NotImplementedError
elif opcode == 'and':
raise NotImplementedError
elif opcode == 'or':
raise NotImplementedError
elif opcode == 'xor':
raise NotImplementedError
elif opcode == 'shl':
raise NotImplementedError
elif opcode == 'shr':
raise NotImplementedError
elif opcode == 'call':
2015-10-17 13:54:28 +00:00
raise NotImplementedError(instr.name)
2015-10-16 22:12:52 +00:00
elif opcode == 'if':
raise NotImplementedError
else:
raise NotImplementedError