Beispiel #1
0
 def _resolve(self, uref):
     """
     Resolve the given unresolved reference. Get the symbol's value or
     re-evaluate an expression and place that value in the reference's
     address. 
     """
     if uref.expr is None: 
         value = self.meta.lookup(uref.ref) 
     else:
         value = uref.expr.eval(self.meta) 
         
     if uref.type == REFERENCE_VALUE: 
         self.mem[uref.address] = vm.size8(value)  
     elif uref.type == REFERENCE_ABSOLUTE: 
         self.mem[uref.address::2] = vm.size16(value)
     elif uref.type == REFERENCE_ZERO_PAGE: 
         self.mem[uref.address] = vm.size8(value) 
     elif uref.type == REFERENCE_RELATIVE: 
         abs_address = vm.size16(value)
         # Branch is relative to PC after opcode and displacement
         # have been consumed. Since abs_address points to where
         # the displacement should go, add one to this value. 
         rel_address = abs_address - (uref.address + 1) 
         assert_branch_displacement(rel_address)
         self.mem[uref.address] = vm.twos_forward(rel_address)
     else:
         assert False 
Beispiel #2
0
def _store_zp(cpu, address, value):
    cpu.mem[vm.size8(address)] = value
Beispiel #3
0
def _load_zp(cpu, address):
    return cpu.mem[vm.size8(address)]
Beispiel #4
0
 def test_size8_negative(self):
     self.assertEquals(vm.SBYTE_MIN, vm.size8(vm.SBYTE_MIN)) 
Beispiel #5
0
 def test_size8(self):
     self.assertEquals(0xff, vm.size8(0xff)) 
Beispiel #6
0
 def _set_register(self, name, value, on=0):
     value = vm.size8(value)
     self._registers[name] = value | on
     [event(name, value) for event in self.register_listeners]
Beispiel #7
0
 def _push(self, value, type):
     self.mem[memmap.STACK_PAGE + self.sp] = vm.size8(value) 
     self.stack_contents[self.sp] = type
     self.sp = (self.sp - 1)  & vm.BITS8 
     if self.sp == vm.BITS8: 
         raise StackError('Stack overflow')
Beispiel #8
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