Exemple #1
0
    def compile_save(self, instr):
        for location in instr.locations:
            if location == REG_A:
                self.emitter.emit(PHA())
            elif location == REG_X:
                self.emitter.emit(TXA())
                self.emitter.emit(PHA())
            elif location == REG_Y:
                self.emitter.emit(TYA())
                self.emitter.emit(PHA())
            else:
                src_label = self.get_label(location.name)
                self.emitter.emit(LDA(Absolute(src_label)))
                self.emitter.emit(PHA())

        self.compile_block(instr.block)

        for location in reversed(instr.locations):
            if location == REG_A:
                self.emitter.emit(PLA())
            elif location == REG_X:
                self.emitter.emit(PLA())
                self.emitter.emit(TAX())
            elif location == REG_Y:
                self.emitter.emit(PLA())
                self.emitter.emit(TAY())
            else:
                src_label = self.get_label(location.name)
                self.emitter.emit(PLA())
                self.emitter.emit(STA(Absolute(src_label)))
Exemple #2
0
 def compile_call(self, instr):
     location = instr.location
     label = self.get_label(instr.location.name)
     location_type = self.get_type(location)
     if isinstance(location_type, RoutineType):
         self.emitter.emit(JSR(Absolute(label)))
     elif isinstance(location_type, VectorType):
         trampoline = self.trampolines.setdefault(
             location, Label(location.name + '_trampoline'))
         self.emitter.emit(JSR(Absolute(trampoline)))
     else:
         raise NotImplementedError(location_type)
Exemple #3
0
 def compile_if(self, instr):
     cls = {
         False: {
             'c': BCC,
             'z': BNE,
             'n': BPL,
         },
         True: {
             'c': BCS,
             'z': BEQ,
             'n': BMI,
         },
     }[instr.inverted].get(instr.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 is not None:
         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)
Exemple #4
0
    def compile_routine(self, routine, next_routine=None):
        assert isinstance(routine, Routine)

        self.current_routine = routine

        if routine.block:
            self.emitter.resolve_label(self.get_label(routine.name))
            self.compile_block(routine.block)

            needs_rts = True
            last_op = self.emitter.get_tail()

            if isinstance(last_op, JSR):
                if isinstance(last_op.operand, Absolute):
                    if isinstance(last_op.operand.value, Label):
                        label = last_op.operand.value
                        self.emitter.retract()
                        self.emitter.emit(JMP(Absolute(label)))
                        last_op = self.emitter.get_tail()

            if isinstance(last_op, JMP):
                needs_rts = False
                if isinstance(last_op.operand, Absolute):
                    if isinstance(last_op.operand.value, Label):
                        if next_routine and last_op.operand.value.name == next_routine.name:
                            self.emitter.retract()

            if needs_rts:
                self.emitter.emit(RTS())

        self.current_routine = None
Exemple #5
0
 def compile_goto(self, instr):
     location = instr.location
     label = self.get_label(instr.location.name)
     location_type = self.get_type(location)
     if isinstance(location_type, RoutineType):
         self.emitter.emit(JMP(Absolute(label)))
     elif isinstance(location_type, VectorType):
         self.emitter.emit(JMP(Indirect(label)))
     else:
         raise NotImplementedError(location_type)
Exemple #6
0
 def compile_dec(self, instr, dest):
     """`instr` is only for reporting purposes"""
     if dest == REG_X:
         self.emitter.emit(DEX())
     elif dest == REG_Y:
         self.emitter.emit(DEY())
     elif isinstance(dest, IndexedRef):
         mode = self.addressing_mode_for_index(dest.index)
         self.emitter.emit(
             DEC(
                 mode(
                     Offset(self.get_label(dest.ref.name),
                            dest.offset.value))))
     else:
         self.emitter.emit(DEC(Absolute(self.get_label(dest.name))))
Exemple #7
0
 def compile_repeat(self, instr):
     top_label = self.emitter.make_label()
     self.compile_block(instr.block)
     if instr.src is None:  # indicates 'repeat forever'
         self.emitter.emit(JMP(Absolute(top_label)))
     else:
         cls = {
             False: {
                 'c': BCC,
                 'z': BNE,
                 'n': BPL,
             },
             True: {
                 'c': BCS,
                 'z': BEQ,
                 'n': BMI,
             },
         }[instr.inverted].get(instr.src.name)
         if cls is None:
             raise UnsupportedOpcodeError(instr)
         self.emitter.emit(cls(Relative(top_label)))
Exemple #8
0
 def compile_cmp(self, instr, src, dest):
     """`instr` is only for reporting purposes"""
     if isinstance(src, LocationRef) and self.get_type(src) == TYPE_WORD:
         src_label = self.get_label(src.name)
         dest_label = self.get_label(dest.name)
         self.emitter.emit(LDA(Absolute(dest_label)))
         self.emitter.emit(CMP(Absolute(src_label)))
         end_label = Label('end_label')
         self.emitter.emit(BNE(Relative(end_label)))
         self.emitter.emit(LDA(Absolute(Offset(dest_label, 1))))
         self.emitter.emit(CMP(Absolute(Offset(src_label, 1))))
         self.emitter.resolve_label(end_label)
         return
     if isinstance(src, ConstantRef) and self.get_type(src) == TYPE_WORD:
         dest_label = self.get_label(dest.name)
         self.emitter.emit(LDA(Absolute(dest_label)))
         self.emitter.emit(CMP(Immediate(Byte(src.low_byte()))))
         end_label = Label('end_label')
         self.emitter.emit(BNE(Relative(end_label)))
         self.emitter.emit(LDA(Absolute(Offset(dest_label, 1))))
         self.emitter.emit(CMP(Immediate(Byte(src.high_byte()))))
         self.emitter.resolve_label(end_label)
         return
     cls = {
         'a': CMP,
         'x': CPX,
         'y': CPY,
     }.get(dest.name)
     if cls is None:
         raise UnsupportedOpcodeError(instr)
     if isinstance(src, ConstantRef):
         self.emitter.emit(cls(Immediate(Byte(src.value))))
     elif isinstance(src, IndexedRef):
         # FIXME might not work for some dest's (that is, cls's)
         mode = self.addressing_mode_for_index(src.index)
         self.emitter.emit(
             cls(
                 mode(Offset(self.get_label(src.ref.name),
                             src.offset.value))))
     else:
         self.emitter.emit(cls(Absolute(self.get_label(src.name))))
Exemple #9
0
    def compile_copy(self, instr, src, dest):

        if isinstance(src, (IndirectRef, IndexedRef)):
            src_ref_type = self.get_type(src.ref)
        else:
            src_type = self.get_type(src)

        if isinstance(dest, (IndirectRef, IndexedRef)):
            dest_ref_type = self.get_type(dest.ref)
        else:
            dest_type = self.get_type(dest)

        if isinstance(src, ConstantRef) and isinstance(
                dest, IndirectRef) and src_type == TYPE_BYTE and isinstance(
                    dest_ref_type, PointerType):
            ### copy 123, [ptr] + y
            dest_label = self.get_label(dest.ref.name)
            self.emitter.emit(LDA(Immediate(Byte(src.value))))
            self.emitter.emit(STA(IndirectY(dest_label)))
        elif isinstance(src, LocationRef) and isinstance(
                dest, IndirectRef) and src_type == TYPE_BYTE and isinstance(
                    dest_ref_type, PointerType):
            ### copy b, [ptr] + y
            src_label = self.get_label(src.name)
            dest_label = self.get_label(dest.ref.name)
            self.emitter.emit(LDA(Absolute(src_label)))
            self.emitter.emit(STA(IndirectY(dest_label)))
        elif isinstance(src, IndirectRef) and isinstance(
                dest, LocationRef) and dest_type == TYPE_BYTE and isinstance(
                    src_ref_type, PointerType):
            ### copy [ptr] + y, b
            src_label = self.get_label(src.ref.name)
            dest_label = self.get_label(dest.name)
            self.emitter.emit(LDA(IndirectY(src_label)))
            self.emitter.emit(STA(Absolute(dest_label)))
        elif isinstance(src, IndirectRef) and isinstance(
                dest, IndirectRef) and isinstance(
                    src_ref_type, PointerType) and isinstance(
                        dest_ref_type, PointerType):
            ### copy [ptra] + y, [ptrb] + y
            src_label = self.get_label(src.ref.name)
            dest_label = self.get_label(dest.ref.name)
            self.emitter.emit(LDA(IndirectY(src_label)))
            self.emitter.emit(STA(IndirectY(dest_label)))
        elif isinstance(src, LocationRef) and isinstance(
                dest, IndexedRef
        ) and src_type == TYPE_WORD and TableType.is_a_table_type(
                dest_ref_type, TYPE_WORD):
            ### copy w, wtab + y
            src_label = self.get_label(src.name)
            dest_label = self.get_label(dest.ref.name)
            mode = self.addressing_mode_for_index(dest.index)
            self.emitter.emit(LDA(Absolute(src_label)))
            self.emitter.emit(STA(mode(Offset(dest_label, dest.offset.value))))
            self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
            self.emitter.emit(
                STA(mode(Offset(dest_label, dest.offset.value + 256))))
        elif isinstance(src, LocationRef) and isinstance(
                dest, IndexedRef) and isinstance(
                    src_type, VectorType) and isinstance(
                        dest_ref_type, TableType) and isinstance(
                            dest_ref_type.of_type, VectorType):
            ### copy vec, vtab + y
            # FIXME this is the exact same as above - can this be simplified?
            src_label = self.get_label(src.name)
            dest_label = self.get_label(dest.ref.name)
            mode = self.addressing_mode_for_index(dest.index)
            self.emitter.emit(LDA(Absolute(src_label)))
            self.emitter.emit(STA(mode(Offset(dest_label, dest.offset.value))))
            self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
            self.emitter.emit(
                STA(mode(Offset(dest_label, dest.offset.value + 256))))
        elif isinstance(src, LocationRef) and isinstance(
                dest, IndexedRef) and isinstance(
                    src_type, RoutineType) and isinstance(
                        dest_ref_type, TableType) and isinstance(
                            dest_ref_type.of_type, VectorType):
            ### copy routine, vtab + y
            src_label = self.get_label(src.name)
            dest_label = self.get_label(dest.ref.name)
            mode = self.addressing_mode_for_index(dest.index)
            self.emitter.emit(LDA(Immediate(HighAddressByte(src_label))))
            self.emitter.emit(STA(mode(Offset(dest_label, dest.offset.value))))
            self.emitter.emit(LDA(Immediate(LowAddressByte(src_label))))
            self.emitter.emit(
                STA(mode(Offset(dest_label, dest.offset.value + 256))))
        elif isinstance(src, ConstantRef) and isinstance(
                dest, IndexedRef
        ) and src_type == TYPE_WORD and TableType.is_a_table_type(
                dest_ref_type, TYPE_WORD):
            ### copy 9999, wtab + y
            dest_label = self.get_label(dest.ref.name)
            mode = self.addressing_mode_for_index(dest.index)
            self.emitter.emit(LDA(Immediate(Byte(src.low_byte()))))
            self.emitter.emit(STA(mode(Offset(dest_label, dest.offset.value))))
            self.emitter.emit(LDA(Immediate(Byte(src.high_byte()))))
            self.emitter.emit(
                STA(mode(Offset(dest_label, dest.offset.value + 256))))
        elif isinstance(src, IndexedRef) and isinstance(
                dest, LocationRef) and TableType.is_a_table_type(
                    src_ref_type, TYPE_WORD) and dest_type == TYPE_WORD:
            ### copy wtab + y, w
            src_label = self.get_label(src.ref.name)
            dest_label = self.get_label(dest.name)
            mode = self.addressing_mode_for_index(src.index)
            self.emitter.emit(LDA(mode(Offset(src_label, src.offset.value))))
            self.emitter.emit(STA(Absolute(dest_label)))
            self.emitter.emit(
                LDA(mode(Offset(src_label, src.offset.value + 256))))
            self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
        elif isinstance(src, IndexedRef) and isinstance(
                dest, LocationRef) and isinstance(
                    dest_type, VectorType) and isinstance(
                        src_ref_type, TableType) and isinstance(
                            src_ref_type.of_type, VectorType):
            ### copy vtab + y, vec
            # FIXME this is the exact same as above - can this be simplified?
            src_label = self.get_label(src.ref.name)
            dest_label = self.get_label(dest.name)
            mode = self.addressing_mode_for_index(src.index)
            self.emitter.emit(LDA(mode(Offset(src_label, src.offset.value))))
            self.emitter.emit(STA(Absolute(dest_label)))
            self.emitter.emit(
                LDA(mode(Offset(src_label, src.offset.value + 256))))
            self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
        elif src_type == TYPE_BYTE and dest_type == TYPE_BYTE and not isinstance(
                src, ConstantRef):
            ### copy b1, b2
            src_label = self.get_label(src.name)
            dest_label = self.get_label(dest.name)
            self.emitter.emit(LDA(Absolute(src_label)))
            self.emitter.emit(STA(Absolute(dest_label)))
        elif src_type == TYPE_WORD and dest_type == TYPE_WORD and isinstance(
                src, ConstantRef):
            ### copy 9999, w
            dest_label = self.get_label(dest.name)
            self.emitter.emit(LDA(Immediate(Byte(src.low_byte()))))
            self.emitter.emit(STA(Absolute(dest_label)))
            self.emitter.emit(LDA(Immediate(Byte(src.high_byte()))))
            self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
        elif src_type == TYPE_WORD and dest_type == TYPE_WORD and not isinstance(
                src, ConstantRef):
            ### copy w1, w2
            src_label = self.get_label(src.name)
            dest_label = self.get_label(dest.name)
            self.emitter.emit(LDA(Absolute(src_label)))
            self.emitter.emit(STA(Absolute(dest_label)))
            self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
            self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
        elif isinstance(src_type, VectorType) and isinstance(
                dest_type, VectorType):
            ### copy v1, v2
            src_label = self.get_label(src.name)
            dest_label = self.get_label(dest.name)
            self.emitter.emit(LDA(Absolute(src_label)))
            self.emitter.emit(STA(Absolute(dest_label)))
            self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
            self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
        elif isinstance(src_type, RoutineType) and isinstance(
                dest_type, VectorType):
            ### copy routine, vec
            src_label = self.get_label(src.name)
            dest_label = self.get_label(dest.name)
            self.emitter.emit(LDA(Immediate(HighAddressByte(src_label))))
            self.emitter.emit(STA(Absolute(dest_label)))
            self.emitter.emit(LDA(Immediate(LowAddressByte(src_label))))
            self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
        else:
            raise NotImplementedError(src_type)
Exemple #10
0
    def compile_single_op(self, instr):

        opcode = instr.opcode
        dest = instr.dest
        src = instr.src

        if opcode == 'ld':
            if dest == REG_A:
                if src == REG_X:
                    self.emitter.emit(TXA())
                elif src == REG_Y:
                    self.emitter.emit(TYA())
                elif isinstance(src, ConstantRef):
                    self.emitter.emit(LDA(Immediate(Byte(src.value))))
                elif isinstance(src, IndexedRef) and src.index == REG_X:
                    self.emitter.emit(
                        LDA(
                            AbsoluteX(
                                Offset(self.get_label(src.ref.name),
                                       src.offset.value))))
                elif isinstance(src, IndexedRef) and src.index == REG_Y:
                    self.emitter.emit(
                        LDA(
                            AbsoluteY(
                                Offset(self.get_label(src.ref.name),
                                       src.offset.value))))
                elif isinstance(src, IndirectRef) and isinstance(
                        self.get_type(src.ref), PointerType):
                    self.emitter.emit(
                        LDA(IndirectY(self.get_label(src.ref.name))))
                else:
                    self.emitter.emit(
                        LDA(
                            self.absolute_or_zero_page(self.get_label(
                                src.name))))
            elif dest == REG_X:
                if src == REG_A:
                    self.emitter.emit(TAX())
                elif isinstance(src, ConstantRef):
                    self.emitter.emit(LDX(Immediate(Byte(src.value))))
                elif isinstance(src, IndexedRef) and src.index == REG_Y:
                    self.emitter.emit(
                        LDX(
                            AbsoluteY(
                                Offset(self.get_label(src.ref.name),
                                       src.offset.value))))
                else:
                    self.emitter.emit(
                        LDX(
                            self.absolute_or_zero_page(self.get_label(
                                src.name))))
            elif dest == REG_Y:
                if src == REG_A:
                    self.emitter.emit(TAY())
                elif isinstance(src, ConstantRef):
                    self.emitter.emit(LDY(Immediate(Byte(src.value))))
                elif isinstance(src, IndexedRef) and src.index == REG_X:
                    self.emitter.emit(
                        LDY(
                            AbsoluteX(
                                Offset(self.get_label(src.ref.name),
                                       src.offset.value))))
                else:
                    self.emitter.emit(
                        LDY(
                            self.absolute_or_zero_page(self.get_label(
                                src.name))))
            else:
                raise UnsupportedOpcodeError(instr)
        elif opcode == 'st':
            if dest == FLAG_C and src == ConstantRef(TYPE_BIT, 0):
                self.emitter.emit(CLC())
            elif dest == FLAG_C and src == ConstantRef(TYPE_BIT, 1):
                self.emitter.emit(SEC())
            else:
                op_cls = {REG_A: STA, REG_X: STX, REG_Y: STY}.get(src, None)

                if isinstance(dest, IndexedRef):
                    mode_cls = {
                        REG_X: AbsoluteX,
                        REG_Y: AbsoluteY,
                    }[dest.index]
                    operand = mode_cls(
                        Offset(self.get_label(dest.ref.name),
                               dest.offset.value))
                elif isinstance(dest, IndirectRef) and isinstance(
                        self.get_type(dest.ref), PointerType):
                    operand = IndirectY(self.get_label(dest.ref.name))
                else:
                    operand = self.absolute_or_zero_page(
                        self.get_label(dest.name))

                if op_cls is None:
                    raise UnsupportedOpcodeError(instr)
                self.emitter.emit(op_cls(operand))
        elif opcode == 'add':
            if dest == REG_X or dest == REG_Y:
                raise UnsupportedOpcodeError(instr)
            if dest == REG_A:
                if isinstance(src, ConstantRef):
                    self.emitter.emit(ADC(Immediate(Byte(src.value))))
                elif isinstance(src, IndexedRef):
                    mode = self.addressing_mode_for_index(src.index)
                    self.emitter.emit(
                        ADC(
                            mode(
                                Offset(self.get_label(src.ref.name),
                                       src.offset.value))))
                else:
                    self.emitter.emit(ADC(Absolute(self.get_label(src.name))))
            elif isinstance(dest, LocationRef) and self.get_type(
                    src) == TYPE_BYTE and self.get_type(dest) == TYPE_BYTE:
                if isinstance(src, ConstantRef):
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(Absolute(dest_label)))
                    self.emitter.emit(ADC(Immediate(Byte(src.low_byte()))))
                    self.emitter.emit(STA(Absolute(dest_label)))
                elif isinstance(src, LocationRef):
                    src_label = self.get_label(src.name)
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(Absolute(dest_label)))
                    self.emitter.emit(ADC(Absolute(src_label)))
                    self.emitter.emit(STA(Absolute(dest_label)))
                else:
                    raise UnsupportedOpcodeError(instr)
            elif isinstance(dest, LocationRef) and self.get_type(
                    src) == TYPE_WORD and self.get_type(dest) == TYPE_WORD:
                if isinstance(src, ConstantRef):
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(Absolute(dest_label)))
                    self.emitter.emit(ADC(Immediate(Byte(src.low_byte()))))
                    self.emitter.emit(STA(Absolute(dest_label)))
                    self.emitter.emit(LDA(Absolute(Offset(dest_label, 1))))
                    self.emitter.emit(ADC(Immediate(Byte(src.high_byte()))))
                    self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
                elif isinstance(src, LocationRef):
                    src_label = self.get_label(src.name)
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(Absolute(dest_label)))
                    self.emitter.emit(ADC(Absolute(src_label)))
                    self.emitter.emit(STA(Absolute(dest_label)))
                    self.emitter.emit(LDA(Absolute(Offset(dest_label, 1))))
                    self.emitter.emit(ADC(Absolute(Offset(src_label, 1))))
                    self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
                else:
                    raise UnsupportedOpcodeError(instr)
            elif isinstance(dest, LocationRef) and self.get_type(
                    src) == TYPE_WORD and isinstance(self.get_type(dest),
                                                     PointerType):
                if isinstance(src, ConstantRef):
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(ZeroPage(dest_label)))
                    self.emitter.emit(ADC(Immediate(Byte(src.low_byte()))))
                    self.emitter.emit(STA(ZeroPage(dest_label)))
                    self.emitter.emit(LDA(ZeroPage(Offset(dest_label, 1))))
                    self.emitter.emit(ADC(Immediate(Byte(src.high_byte()))))
                    self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
                elif isinstance(src, LocationRef):
                    src_label = self.get_label(src.name)
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(ZeroPage(dest_label)))
                    self.emitter.emit(ADC(Absolute(src_label)))
                    self.emitter.emit(STA(ZeroPage(dest_label)))
                    self.emitter.emit(LDA(ZeroPage(Offset(dest_label, 1))))
                    self.emitter.emit(ADC(Absolute(Offset(src_label, 1))))
                    self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
                else:
                    raise UnsupportedOpcodeError(instr)
            else:
                raise UnsupportedOpcodeError(instr)
        elif opcode == 'sub':
            if dest == REG_X or dest == REG_Y:
                raise UnsupportedOpcodeError(instr)
            if dest == REG_A:
                if isinstance(src, ConstantRef):
                    self.emitter.emit(SBC(Immediate(Byte(src.value))))
                elif isinstance(src, IndexedRef):
                    mode = self.addressing_mode_for_index(src.index)
                    self.emitter.emit(
                        SBC(
                            mode(
                                Offset(self.get_label(src.ref.name),
                                       src.offset.value))))
                else:
                    self.emitter.emit(SBC(Absolute(self.get_label(src.name))))
            elif isinstance(dest, LocationRef) and self.get_type(
                    src) == TYPE_BYTE and self.get_type(dest) == TYPE_BYTE:
                if isinstance(src, ConstantRef):
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(Absolute(dest_label)))
                    self.emitter.emit(SBC(Immediate(Byte(src.low_byte()))))
                    self.emitter.emit(STA(Absolute(dest_label)))
                elif isinstance(src, LocationRef):
                    src_label = self.get_label(src.name)
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(Absolute(dest_label)))
                    self.emitter.emit(SBC(Absolute(src_label)))
                    self.emitter.emit(STA(Absolute(dest_label)))
                else:
                    raise UnsupportedOpcodeError(instr)
            elif isinstance(dest, LocationRef) and self.get_type(
                    src) == TYPE_WORD and self.get_type(dest) == TYPE_WORD:
                if isinstance(src, ConstantRef):
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(Absolute(dest_label)))
                    self.emitter.emit(SBC(Immediate(Byte(src.low_byte()))))
                    self.emitter.emit(STA(Absolute(dest_label)))
                    self.emitter.emit(LDA(Absolute(Offset(dest_label, 1))))
                    self.emitter.emit(SBC(Immediate(Byte(src.high_byte()))))
                    self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
                elif isinstance(src, LocationRef):
                    src_label = self.get_label(src.name)
                    dest_label = self.get_label(dest.name)
                    self.emitter.emit(LDA(Absolute(dest_label)))
                    self.emitter.emit(SBC(Absolute(src_label)))
                    self.emitter.emit(STA(Absolute(dest_label)))
                    self.emitter.emit(LDA(Absolute(Offset(dest_label, 1))))
                    self.emitter.emit(SBC(Absolute(Offset(src_label, 1))))
                    self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
                else:
                    raise UnsupportedOpcodeError(instr)
            else:
                raise UnsupportedOpcodeError(instr)
        elif opcode == 'cmp':
            self.compile_cmp(instr, instr.src, instr.dest)
        elif opcode in (
                'and',
                'or',
                'xor',
        ):
            cls = {
                'and': AND,
                'or': ORA,
                'xor': EOR,
            }[opcode]
            if dest == REG_A:
                if isinstance(src, ConstantRef):
                    self.emitter.emit(cls(Immediate(Byte(src.value))))
                elif isinstance(src, IndexedRef):
                    mode = self.addressing_mode_for_index(src.index)
                    self.emitter.emit(
                        cls(
                            mode(
                                Offset(self.get_label(src.ref.name),
                                       src.offset.value))))
                else:
                    self.emitter.emit(
                        cls(
                            self.absolute_or_zero_page(self.get_label(
                                src.name))))
            else:
                raise UnsupportedOpcodeError(instr)
        elif opcode == 'inc':
            self.compile_inc(instr, instr.dest)
        elif opcode == 'dec':
            self.compile_dec(instr, instr.dest)
        elif opcode in ('shl', 'shr'):
            cls = {
                'shl': ROL,
                'shr': ROR,
            }[opcode]
            if dest == REG_A:
                self.emitter.emit(cls())
            elif isinstance(dest, IndexedRef):
                mode = self.addressing_mode_for_index(dest.index)
                self.emitter.emit(
                    cls(
                        mode(
                            Offset(self.get_label(dest.ref.name),
                                   dest.offset.value))))
            else:
                self.emitter.emit(
                    cls(self.absolute_or_zero_page(self.get_label(dest.name))))
        elif opcode == 'copy':
            self.compile_copy(instr, instr.src, instr.dest)
        elif opcode == 'trash':
            pass
        elif opcode == 'nop':
            self.emitter.emit(NOP())
        else:
            raise NotImplementedError(opcode)
Exemple #11
0
 def absolute_or_zero_page(self, label):
     if label.addr is not None and label.addr < 256:
         return ZeroPage(label)
     else:
         return Absolute(label)