diff --git a/src/sixtypical/compiler.py b/src/sixtypical/compiler.py index 877bb05..be5b5a8 100644 --- a/src/sixtypical/compiler.py +++ b/src/sixtypical/compiler.py @@ -7,12 +7,13 @@ from sixtypical.model import ( ) from sixtypical.emitter import Label, Byte from sixtypical.gen6502 import ( - Immediate, Absolute, + Immediate, Absolute, Relative, LDA, LDX, LDY, STA, STX, STY, CLC, SEC, ADC, SBC, ROL, ROR, - RTS, JSR, INC, INX, INY, DEC, DEX, DEY, CMP, CPX, CPY, AND, ORA, EOR, + BCC, BNE, + JMP, JSR, RTS, ) @@ -58,10 +59,8 @@ class Compiler(object): def compile_block(self, block): assert isinstance(block, Block) - label = self.emitter.make_label() for instr in block.instrs: self.compile_instr(instr) - return label def compile_instr(self, instr): assert isinstance(instr, Instr) @@ -168,6 +167,22 @@ class Compiler(object): label = self.labels[instr.name] self.emitter.emit(JSR(Absolute(label))) elif opcode == 'if': - raise NotImplementedError + cls = { + 'c': BCC, + 'z': BNE, + }.get(src.name) + if cls is None: + raise UnsupportedOpcodeError(instr) + else_label = Label('else_label') + self.emitter.emit(cls(Relative(else_label))) + self.compile_block(instr.block1) + if instr.block2: + 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) else: raise NotImplementedError diff --git a/src/sixtypical/gen6502.py b/src/sixtypical/gen6502.py index dba0ead..f0612bf 100644 --- a/src/sixtypical/gen6502.py +++ b/src/sixtypical/gen6502.py @@ -8,6 +8,9 @@ class AddressingMode(object): """Size of the operand for the mode (not including the opcode)""" raise NotImplementedError + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.value) + class Implied(AddressingMode): def size(self): @@ -31,9 +34,6 @@ class Immediate(AddressingMode): def serialize(self): return self.value.serialize() - def __repr__(self): - return "%s(%r)" % (self.__class__.__name__, self.value) - class Absolute(AddressingMode): def __init__(self, value): @@ -46,8 +46,18 @@ class Absolute(AddressingMode): def serialize(self): return self.value.serialize() - def __repr__(self): - return "%s(%r)" % (self.__class__.__name__, self.value) + +class Relative(AddressingMode): + def __init__(self, value): + assert isinstance(value, (Byte, Label)) + self.value = value + + def size(self): + return 1 + + def serialize(self): + # HA + return chr(0xff) class Opcode(Emittable): @@ -81,6 +91,18 @@ class AND(Opcode): } +class BCC(Opcode): + opcodes = { + Relative: 0x90, + } + + +class BNE(Opcode): + opcodes = { + Relative: 0xd0, + } + + class CLC(Opcode): opcodes = { Implied: 0x18 @@ -151,6 +173,12 @@ class INY(Opcode): } +class JMP(Opcode): + opcodes = { + Absolute: 0x4c, + } + + class JSR(Opcode): opcodes = { Absolute: 0x20, diff --git a/tests/SixtyPical Compilation.md b/tests/SixtyPical Compilation.md index c7772cc..bbc343a 100644 --- a/tests/SixtyPical Compilation.md +++ b/tests/SixtyPical Compilation.md @@ -118,3 +118,17 @@ Some instructions. | shr a | } = 00c0a900a200a0008d46c08e46c08c46c0381869016d46c0e901ed46c0ee46c0e8c8ce46c0ca8829ff2d46c009ff0d46c049ff4d46c0c901cd46c0e001ec46c0c001cc46c02a6a60 + +Compiling `if`. + + | routine main + | trashes a, x, y, z, n, c, v + | { + | ld a, 0 + | if z { + | ld y, 1 + | } else { + | ld y, 2 + | } + | } + = 00c0