Exemple #1
0
    def compile_reset(self, instr):
        table_name = self.pointer_assoc[instr.pointer.name]
        src_label = Offset(self.get_label(table_name), instr.offset.value)
        dest_label = self.get_label(instr.pointer.name)

        self.emitter.emit(LDA(Immediate(HighAddressByte(src_label))))
        self.emitter.emit(STA(ZeroPage(dest_label)))
        self.emitter.emit(LDA(Immediate(LowAddressByte(src_label))))
        self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
Exemple #2
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 #3
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 #4
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)