8 | 8 |
TableType, PointerType, RoutineType, VectorType,
|
9 | 9 |
REG_A, REG_X, REG_Y, FLAG_C
|
10 | 10 |
)
|
11 | |
from sixtypical.emitter import Byte, Word, Table, Label, Offset, LowAddressByte, HighAddressByte
|
|
11 |
from sixtypical.emitter import Byte, Word, Table, Label, Offset, LowAddressByte, HighAddressByte, Emitter
|
12 | 12 |
from sixtypical.gen6502 import (
|
13 | 13 |
Immediate, Absolute, AbsoluteX, AbsoluteY, ZeroPage, Indirect, IndirectY, Relative,
|
14 | 14 |
LDA, LDX, LDY, STA, STX, STY,
|
|
156 | 156 |
self.emitter.resolve_bss_label(label)
|
157 | 157 |
|
158 | 158 |
def compile_routine(self, routine, next_routine=None):
|
|
159 |
assert isinstance(routine, Routine)
|
|
160 |
|
159 | 161 |
self.current_routine = routine
|
160 | |
self.skip_final_goto = (next_routine is not None)
|
161 | |
self.final_goto_seen = False
|
162 | |
assert isinstance(routine, Routine)
|
|
162 |
saved_emitter = self.emitter
|
|
163 |
self.emitter = Emitter(saved_emitter.addr)
|
163 | 164 |
if routine.block:
|
164 | 165 |
self.emitter.resolve_label(self.get_label(routine.name))
|
165 | 166 |
self.compile_block(routine.block)
|
166 | |
if not self.final_goto_seen:
|
|
167 |
|
|
168 |
needs_rts = True
|
|
169 |
if self.emitter.accum:
|
|
170 |
last_op = self.emitter.accum[-1]
|
|
171 |
if isinstance(last_op, JMP):
|
|
172 |
needs_rts = False
|
|
173 |
if isinstance(last_op.operand, Absolute):
|
|
174 |
if isinstance(last_op.operand.value, Label):
|
|
175 |
if next_routine and last_op.operand.value.name == next_routine.name:
|
|
176 |
self.emitter.retract()
|
|
177 |
|
|
178 |
if needs_rts:
|
167 | 179 |
self.emitter.emit(RTS())
|
|
180 |
|
|
181 |
saved_emitter.emit(*self.emitter.accum)
|
|
182 |
self.emitter = saved_emitter
|
168 | 183 |
self.current_routine = None
|
169 | |
self.skip_final_goto = False
|
170 | 184 |
|
171 | 185 |
def compile_block(self, block):
|
172 | 186 |
assert isinstance(block, Block)
|
|
440 | 454 |
raise NotImplementedError(location_type)
|
441 | 455 |
|
442 | 456 |
def compile_goto(self, instr):
|
443 | |
self.final_goto_seen = True
|
444 | |
if self.skip_final_goto:
|
445 | |
pass
|
446 | |
else:
|
447 | |
location = instr.location
|
448 | |
label = self.get_label(instr.location.name)
|
449 | |
location_type = self.get_type(location)
|
450 | |
if isinstance(location_type, RoutineType):
|
451 | |
self.emitter.emit(JMP(Absolute(label)))
|
452 | |
elif isinstance(location_type, VectorType):
|
453 | |
self.emitter.emit(JMP(Indirect(label)))
|
454 | |
else:
|
455 | |
raise NotImplementedError(location_type)
|
|
457 |
location = instr.location
|
|
458 |
label = self.get_label(instr.location.name)
|
|
459 |
location_type = self.get_type(location)
|
|
460 |
if isinstance(location_type, RoutineType):
|
|
461 |
self.emitter.emit(JMP(Absolute(label)))
|
|
462 |
elif isinstance(location_type, VectorType):
|
|
463 |
self.emitter.emit(JMP(Indirect(label)))
|
|
464 |
else:
|
|
465 |
raise NotImplementedError(location_type)
|
456 | 466 |
|
457 | 467 |
def compile_cmp(self, instr, src, dest):
|
458 | 468 |
"""`instr` is only for reporting purposes"""
|
|
665 | 675 |
else_label = Label('else_label')
|
666 | 676 |
self.emitter.emit(cls(Relative(else_label)))
|
667 | 677 |
self.compile_block(instr.block1)
|
|
678 |
|
668 | 679 |
if instr.block2 is not None:
|
669 | |
end_label = Label('end_label')
|
670 | |
self.emitter.emit(JMP(Absolute(end_label)))
|
671 | |
self.emitter.resolve_label(else_label)
|
672 | |
self.compile_block(instr.block2)
|
673 | |
self.emitter.resolve_label(end_label)
|
|
680 |
if instr.block1.shallow_contains_goto:
|
|
681 |
self.emitter.resolve_label(else_label)
|
|
682 |
self.compile_block(instr.block2)
|
|
683 |
else:
|
|
684 |
end_label = Label('end_label')
|
|
685 |
self.emitter.emit(JMP(Absolute(end_label)))
|
|
686 |
self.emitter.resolve_label(else_label)
|
|
687 |
self.compile_block(instr.block2)
|
|
688 |
self.emitter.resolve_label(end_label)
|
674 | 689 |
else:
|
675 | 690 |
self.emitter.resolve_label(else_label)
|
676 | 691 |
|