def assemble_extended_direct_operand(self, operand, opcode_key, statement, opcode_bytes): if isinstance(operand.address, Label): result = self.assemble_label_operand(operand.address) else: result = (hi(operand.address), lo(operand.address)) return bytes(result)
def value_to_bytes(self, unsigned_offset, operand_bytes_length): if operand_bytes_length == 1: result = bytes((unsigned_offset, )) elif operand_bytes_length == 2: result = bytes((hi(unsigned_offset), lo(unsigned_offset))) else: assert False, f"Unexpected operand bytes length {operand_bytes_length}" return result
def _(statement, asm): operand = statement.operand opcodes = OPCODES[statement.mnemonic] opcode_key = single(operand.codes & opcodes.keys()) opcode = opcodes[opcode_key] asm._opcode_bytes = (opcode, ) if opcode <= 0xFF else (hi(opcode), lo(opcode)) operand_bytes = assemble_operand(operand, opcode_key, asm, statement) asm._extend(asm._opcode_bytes + operand_bytes)
def assemble_label_operand(self, label): if label.name in self._label_addresses: target_address = self._label_addresses[label.name] self._unresolved_labels.discard(label) result = (hi(target_address), lo(target_address)) else: self._more_passes_required = True self._unresolved_labels.add(label) result = (0, 0) self._unreferenced_labels.discard(label) return result
def assemble_immediate_operand(self, operand, opcode_key, statement, opcode_bytes): if isinstance(operand, Label): result = self.assemble_label_operand(operand) else: assert statement.inherent_register.width in {1, 2} if statement.inherent_register.width == 1: result = (operand.value, ) elif statement.inherent_register.width == 2: result = (hi(operand.value), lo(operand.value)) else: assert False, f"Unexpected inherent register width {statement.inherent_register.width}" return bytes(result)
def _(operand, opcode_key, asm, statement): # If we know the address of the label, use it if operand.name in asm._label_addresses: target_address = asm._label_addresses[operand.name] if opcode_key in branch_operand_widths: operand_bytes_length = branch_operand_widths[opcode_key] offset = target_address - asm.pos - len( asm._opcode_bytes) - operand_bytes_length unsigned_offset = twos_complement(offset, operand_bytes_length * 8) if opcode_key == REL8: return (unsigned_offset, ) elif opcode_key == REL16: return (hi(unsigned_offset), lo(unsigned_offset)) else: assert opcode_key is IMM return (hi(target_address), lo(target_address)) else: asm._more_passes_required = True if opcode_key in branch_operand_widths: return (0, ) * branch_operand_widths[opcode_key] else: assert opcode_key is IMM return (0, 0)
def assemble_indexed_operand(self, operand: Indexed, opcode_key, statement, opcode_bytes): if operand.base in RR: rr = RR[operand.base] if operand.offset in ACCUMULATOR_OFFSET_POST_BYTE: # Accumulator offset post_byte = ACCUMULATOR_OFFSET_POST_BYTE[operand.offset] post_byte |= rr << 5 return bytes((post_byte, )) elif isinstance(operand.offset, Integral): if operand.offset == 0: post_byte = 0b10000100 post_byte |= rr << 5 return bytes((post_byte, )) elif -16 <= operand.offset <= +15: # 5-bit offset post_byte = twos_complement(operand.offset, 5) post_byte |= rr << 5 return bytes((post_byte, )) elif -128 <= operand.offset <= +127: # 8-bit offset post_byte = 0b10001000 post_byte |= rr << 5 offset_byte = twos_complement(operand.offset, 8) return bytes((post_byte, offset_byte)) elif -32768 <= operand.offset <= +32767: # 16-bit offset post_byte = 0b10001001 post_byte |= rr << 5 offset_bytes = twos_complement(operand.offset, 16) return bytes( (post_byte, hi(offset_bytes), lo(offset_bytes))) else: raise ValueError( f"Cannot use indexed addressing offset {operand.offset} with base {operand.base}" ) elif isinstance(operand.base, AutoIncrementedRegister): if operand.base.register not in RR: raise ValueError( f"Cannot use auto pre-/post- increment or decrement with register {operand.base.register}" ) rr = RR[operand.base.register] post_byte = INDEX_CREMENT_POST_BYTE[operand.base.delta] post_byte |= rr << 5 return bytes((post_byte, )) else: raise ValueError( f"Cannot use {operand.base} as a base register for indexed addressing modes" )
def _(operand, opcode_key, asm, statement): assert statement.inherent_register.width in {1, 2} if statement.inherent_register.width == 1: return (operand.value, ) elif statement.inherent_register.width == 2: return (hi(operand.value), lo(operand.value))