1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-11-25 23:49:17 +00:00

Compiler object, labels, compile 'call'... It prints 'A'!

This commit is contained in:
Chris Pressey 2015-10-17 15:06:50 +01:00
parent 2ffff3bbdb
commit 643a48a2c5
7 changed files with 115 additions and 87 deletions

View File

@ -33,9 +33,7 @@ TODO
For 0.3:
* extern routines.
* generate 6502 code for all SixtyPical instructions.
* a little demo that actually compiles and does something on a C64 emulator.
For 0.4:

View File

@ -21,7 +21,7 @@ from sixtypical.parser import Parser
from sixtypical.evaluator import eval_program
from sixtypical.analyzer import analyze_program
from sixtypical.emitter import Emitter, Byte, Word
from sixtypical.compiler import compile_program
from sixtypical.compiler import Compiler
if __name__ == '__main__':
@ -75,7 +75,8 @@ if __name__ == '__main__':
emitter.emit(Word(start_addr))
for byte in header:
emitter.emit(Byte(byte))
compile_program(program, emitter)
compiler = Compiler(emitter)
compiler.compile_program(program)
if options.debug:
print repr(emitter.accum)
else:

12
eg/print.60p Normal file
View File

@ -0,0 +1,12 @@
routine chrout
inputs a
trashes a
@ 65490
routine main
inputs a
trashes a, z, n
{
ld a, 65
call chrout
}

View File

@ -5,10 +5,10 @@ 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.emitter import Label, Byte
from sixtypical.gen6502 import (
Immediate, Absolute,
LDA, LDX, LDY, STA, STX, STY, CLC, SEC, ADC, RTS
LDA, LDX, LDY, STA, STX, STY, CLC, SEC, ADC, RTS, JSR
)
@ -16,31 +16,37 @@ class UnsupportedOpcodeError(KeyError):
pass
def compile_program(program, emitter):
class Compiler(object):
def __init__(self, emitter):
self.emitter = emitter
self.routines = {}
self.labels = {}
def compile_program(self, program):
assert isinstance(program, Program)
routines = {r.name: r for r in program.routines}
for routine in program.routines:
compile_routine(routine, emitter, 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
for routine in program.routines:
self.compile_routine(routine)
def compile_routine(routine, emitter, routines):
def compile_routine(self, routine):
assert isinstance(routine, Routine)
label = emitter.make_label(routine.name)
if routine.block:
compile_block(routine.block, emitter, routines)
emitter.emit(RTS())
return label
self.compile_block(routine.block)
self.emitter.emit(RTS())
def compile_block(block, emitter, routines):
def compile_block(self, block):
assert isinstance(block, Block)
label = emitter.make_label()
label = self.emitter.make_label()
for instr in block.instrs:
compile_instr(instr, emitter, routines)
self.compile_instr(instr)
return label
def compile_instr(instr, emitter, routines):
def compile_instr(self, instr):
assert isinstance(instr, Instr)
opcode = instr.opcode
dest = instr.dest
@ -49,9 +55,9 @@ def compile_instr(instr, emitter, routines):
if opcode == 'ld':
if dest == REG_A:
if isinstance(src, ConstantRef):
emitter.emit(LDA(Immediate(Byte(src.value))))
self.emitter.emit(LDA(Immediate(Byte(src.value))))
else:
emitter.emit(LDA(Absolute(src.label)))
self.emitter.emit(LDA(Absolute(src.label)))
elif dest == REG_X:
pass
elif dest == REG_Y:
@ -60,23 +66,23 @@ def compile_instr(instr, emitter, routines):
raise UnsupportedOpcodeError(instr)
elif opcode == 'st':
if dest == FLAG_C and src == ConstantRef(0):
emitter.emit(CLC())
self.emitter.emit(CLC())
elif dest == FLAG_C and src == ConstantRef(1):
emitter.emit(SEC())
self.emitter.emit(SEC())
elif src == REG_A:
emitter.emit(STA(Absolute(dest.label)))
self.emitter.emit(STA(Absolute(dest.label)))
elif src == REG_X:
emitter.emit(STX(Absolute(dest.label)))
self.emitter.emit(STX(Absolute(dest.label)))
elif src == REG_Y:
emitter.emit(STY(Absolute(dest.label)))
self.emitter.emit(STY(Absolute(dest.label)))
else:
raise UnsupportedOpcodeError(instr)
elif opcode == 'add':
if dest == REG_A:
if isinstance(src, ConstantRef):
emitter.emit(ADC(Immediate(Byte(src.value))))
self.emitter.emit(ADC(Immediate(Byte(src.value))))
else:
emitter.emit(ADC(Absolute(src.label)))
self.emitter.emit(ADC(Absolute(src.label)))
else:
raise UnsupportedOpcodeError(instr)
elif opcode == 'sub':
@ -98,7 +104,8 @@ def compile_instr(instr, emitter, routines):
elif opcode == 'shr':
raise NotImplementedError
elif opcode == 'call':
raise NotImplementedError(instr.name)
label = self.labels[instr.name]
self.emitter.emit(JSR(Absolute(label)))
elif opcode == 'if':
raise NotImplementedError
else:

View File

@ -58,6 +58,10 @@ class Label(Emittable):
assert self.addr is not None, "unresolved label: %s" % self.name
return Word(self.addr).serialize()
def __repr__(self):
addrs = ', addr=%r' % self.addr if self.addr is not None else ''
return "%s(%r%s)" % (self.__class__.__name__, self.name, addrs)
class Emitter(object):
def __init__(self, addr):

View File

@ -123,6 +123,12 @@ class INY(Opcode):
}
class JSR(Opcode):
opcodes = {
Absolute: 0x20,
}
class LDA(Opcode):
opcodes = {
Immediate: 0xa9,

View File

@ -44,4 +44,4 @@ Call extern.
| ld a, 65
| call chrout
| }
= 00c018690460
= 00c0a94120d2ff60