Implement compiling `if`, but we need relative addressing first.
Chris Pressey
9 years ago
6 | 6 | ) |
7 | 7 | from sixtypical.emitter import Label, Byte |
8 | 8 | from sixtypical.gen6502 import ( |
9 | Immediate, Absolute, | |
9 | Immediate, Absolute, Relative, | |
10 | 10 | LDA, LDX, LDY, STA, STX, STY, |
11 | 11 | CLC, SEC, ADC, SBC, ROL, ROR, |
12 | RTS, JSR, | |
13 | 12 | INC, INX, INY, DEC, DEX, DEY, |
14 | 13 | CMP, CPX, CPY, AND, ORA, EOR, |
14 | BCC, BNE, | |
15 | JMP, JSR, RTS, | |
15 | 16 | ) |
16 | 17 | |
17 | 18 | |
57 | 58 | |
58 | 59 | def compile_block(self, block): |
59 | 60 | assert isinstance(block, Block) |
60 | label = self.emitter.make_label() | |
61 | 61 | for instr in block.instrs: |
62 | 62 | self.compile_instr(instr) |
63 | return label | |
64 | 63 | |
65 | 64 | def compile_instr(self, instr): |
66 | 65 | assert isinstance(instr, Instr) |
167 | 166 | label = self.labels[instr.name] |
168 | 167 | self.emitter.emit(JSR(Absolute(label))) |
169 | 168 | elif opcode == 'if': |
170 | raise NotImplementedError | |
169 | cls = { | |
170 | 'c': BCC, | |
171 | 'z': BNE, | |
172 | }.get(src.name) | |
173 | if cls is None: | |
174 | raise UnsupportedOpcodeError(instr) | |
175 | else_label = Label('else_label') | |
176 | self.emitter.emit(cls(Relative(else_label))) | |
177 | self.compile_block(instr.block1) | |
178 | if instr.block2: | |
179 | end_label = Label('end_label') | |
180 | self.emitter.emit(JMP(Absolute(end_label))) | |
181 | self.emitter.resolve_label(else_label) | |
182 | self.compile_block(instr.block2) | |
183 | self.emitter.resolve_label(end_label) | |
184 | else: | |
185 | self.emitter.resolve_label(else_label) | |
171 | 186 | else: |
172 | 187 | raise NotImplementedError |
6 | 6 | def size(self): |
7 | 7 | """Size of the operand for the mode (not including the opcode)""" |
8 | 8 | raise NotImplementedError |
9 | ||
10 | def __repr__(self): | |
11 | return "%s(%r)" % (self.__class__.__name__, self.value) | |
9 | 12 | |
10 | 13 | |
11 | 14 | class Implied(AddressingMode): |
30 | 33 | def serialize(self): |
31 | 34 | return self.value.serialize() |
32 | 35 | |
33 | def __repr__(self): | |
34 | return "%s(%r)" % (self.__class__.__name__, self.value) | |
35 | ||
36 | 36 | |
37 | 37 | class Absolute(AddressingMode): |
38 | 38 | def __init__(self, value): |
45 | 45 | def serialize(self): |
46 | 46 | return self.value.serialize() |
47 | 47 | |
48 | def __repr__(self): | |
49 | return "%s(%r)" % (self.__class__.__name__, self.value) | |
48 | ||
49 | class Relative(AddressingMode): | |
50 | def __init__(self, value): | |
51 | assert isinstance(value, (Byte, Label)) | |
52 | self.value = value | |
53 | ||
54 | def size(self): | |
55 | return 1 | |
56 | ||
57 | def serialize(self): | |
58 | # HA | |
59 | return chr(0xff) | |
50 | 60 | |
51 | 61 | |
52 | 62 | class Opcode(Emittable): |
80 | 90 | } |
81 | 91 | |
82 | 92 | |
93 | class BCC(Opcode): | |
94 | opcodes = { | |
95 | Relative: 0x90, | |
96 | } | |
97 | ||
98 | ||
99 | class BNE(Opcode): | |
100 | opcodes = { | |
101 | Relative: 0xd0, | |
102 | } | |
103 | ||
104 | ||
83 | 105 | class CLC(Opcode): |
84 | 106 | opcodes = { |
85 | 107 | Implied: 0x18 |
150 | 172 | } |
151 | 173 | |
152 | 174 | |
175 | class JMP(Opcode): | |
176 | opcodes = { | |
177 | Absolute: 0x4c, | |
178 | } | |
179 | ||
180 | ||
153 | 181 | class JSR(Opcode): |
154 | 182 | opcodes = { |
155 | 183 | Absolute: 0x20, |
117 | 117 | | shr a |
118 | 118 | | } |
119 | 119 | = 00c0a900a200a0008d46c08e46c08c46c0381869016d46c0e901ed46c0ee46c0e8c8ce46c0ca8829ff2d46c009ff0d46c049ff4d46c0c901cd46c0e001ec46c0c001cc46c02a6a60 |
120 | ||
121 | Compiling `if`. | |
122 | ||
123 | | routine main | |
124 | | trashes a, x, y, z, n, c, v | |
125 | | { | |
126 | | ld a, 0 | |
127 | | if z { | |
128 | | ld y, 1 | |
129 | | } else { | |
130 | | ld y, 2 | |
131 | | } | |
132 | | } | |
133 | = 00c0 |