예제 #1
0
def one_memory(cpu, oper, mode):
    """
    See 
    :data:`~mach8.operations.DEC`, 
    :data:`~mach8.operations.INC`, 
    """
    address = _fetch_address(cpu, mode) 
    operand = _load_am(cpu, mode, address=address) 
    if   oper == op.DEC: value = vm.mask8(operand - 1)
    elif oper == op.INC: value = vm.mask8(operand + 1)
    _flags(cpu, value) 
    _store_am(cpu, mode, value, address=address) 
예제 #2
0
def one_register(cpu, oper, mode):
    """
    See 
    :data:`~mach8.operations.DEX`, 
    :data:`~mach8.operations.INX`, 
    :data:`~mach8.operations.DEY`,
    :data:`~mach8.operations.INY`,
    """
    if   oper == op.DEX: cpu.x = vm.mask8(cpu.x - 1); result = cpu.x 
    elif oper == op.INX: cpu.x = vm.mask8(cpu.x + 1); result = cpu.x 
    elif oper == op.DEY: cpu.y = vm.mask8(cpu.y - 1); result = cpu.y 
    elif oper == op.INY: cpu.y = vm.mask8(cpu.y + 1); result = cpu.y
    else: assert False
    _flags(cpu, result) 
예제 #3
0
 def _data_int(self, value):
     """
     Insert numeric data at the current position.
     """
     if vm.is8(value) or vm.is8s(value): 
         self.mem[self.position] = vm.mask8(value)
         self.position += 1
     elif vm.is16(value): 
         self.mem[self.position::2] = value
         self.position += 2
     else: 
         raise OverflowError('Value out of range: ${:X} {:d}'
                            .format(value, value))
예제 #4
0
 def test_mask8_mask(self):
     self.assertEquals(0xff, vm.mask8(0x12ff)) 
예제 #5
0
    def assemble(self, *args):
        """
        To assemble an instruction, call the object with the 
        :class:`instruction <mach8.instruction.Instruction>` and the 
        argument (if necessary). Example:: 
    
           a = Assembler(mem, position=0x4000) 
           _;    a(lda_imm, 0x42) 
        
        Call the object with a string to create a label at the current address. 
        Forward references allowed. Example::
     
           _;    a(jmp_abs, 'skip_brk')
           _;    a(brk)
           _; a('skip_brk')
           _;    a(nop) 
       
        Use :mod:`expressions <mach8.expressions>` for enhanced disassembly 
        display:: 
    
           _;    a(lda_imm, 9 + 2)     # Disassembles to lda #$0B
           _;    a(lda_imm, add(9, 2)) # Disassembles to lda #[9 + 2]
        
        Returns the address where the instruction was assembled. 

        Note: Any reference to a label or alias that does not exist is 
        considered to be an unresolved reference and will be entered in as a 
        zero until resolved. Invoking :meth:`verify` will raise a 
        :class:`SymbolUnresolvedError` if there are any outstanding unresolved 
        references. 
        """
        instruction_address = self.position
        if len(args) == 0: 
            return instruction_address
        
        # Label definition
        if isinstance(args[0], str):
            if len(args) != 1: 
                raise TypeError('Expected 1 argument but received {:d}' 
                                .format(len(args)))
            label = args[0] 
            self.label(label) 
            return 
        
        inst = args[0]
        required_args = 1 if inst.addressing_mode in AM_NO_ARGUMENT else 2 
        if len(args) != required_args: 
            raise TypeError('Expected {:d} arguments but received {:d}' 
                            .format(required_args, len(args)))
        
        self._check_meta() 
        if inst.addressing_mode in AM_ADDRESS_16:
            self.meta.clear(instruction_address + 1, 
                            instruction_address + 3) 
            address = self.meta.add_reference(args[1], instruction_address, 
                                              REFERENCE_ABSOLUTE) 
            address = vm.size16(address) 
            self._pc.store(inst.opcode) 
            self._pc.store2(address) 
        elif inst.addressing_mode in AM_ADDRESS_8: 
            self.meta.clear(instruction_address + 1, 
                            instruction_address + 2) 
            address = self.meta.add_reference(args[1], instruction_address, 
                                              REFERENCE_ZERO_PAGE) 
            address = vm.size8(address) 
            self._pc.store(inst.opcode) 
            self._pc.store(address) 
        elif inst.addressing_mode == am.IMM:
            self.meta.clear(instruction_address + 1, 
                            instruction_address + 2) 
            value = self.meta.add_reference(args[1], instruction_address, 
                                            REFERENCE_VALUE) 
            value = vm.size8s(value) 
            self._pc.store(inst.opcode) 
            self._pc.store(vm.mask8(value)) 
        elif inst.addressing_mode in AM_NO_ARGUMENT:
            self._pc.store(inst.opcode)
        elif inst.addressing_mode == am.REL:
            self.meta.clear(instruction_address + 1, 
                            instruction_address + 2) 
            abs_address = self.meta.add_reference(args[1], instruction_address, 
                                                  REFERENCE_RELATIVE) 
            if self.meta.lookup(args[1], default=None) is not None:  
                # Branch is relative to PC after instruction has been consumed. 
                # Since we have not yet 'consumed' it, the PC has to be 
                # adjusted by two (opcode and offset) 
                rel_address = abs_address - (self.position + 2)
                assert_branch_displacement(rel_address)
                # TODO: Cleanup 
                address = rel_address & vm.BITS8 
            else: 
                address = 0
            self._pc.store(inst.opcode) 
            self._pc.store(address)  
        else: 
            raise ValueError('Invalid instruction: ' + str(inst)) 
        self._new_position = True