def resolve_symbols(self, symbol_table): """ Given a symbol table, searches the operands for any symbols, and resolves them with values from the symbol table. Returns a (possibly) new Operand class type as a result of symbol resolution. :param symbol_table: the symbol table to search :return: self, or a new Operand class type with a resolved value """ if self.is_type(OperandType.EXPRESSION): return self.resolve_expression(symbol_table) if not self.value.is_type(ValueType.SYMBOL): return self symbol = self.get_symbol(self.value.ascii(), symbol_table) if symbol.is_type(ValueType.ADDRESS): self.value = AddressValue(symbol.int) if self.type == OperandType.UNKNOWN: return ExtendedOperand(self.operand_string, self.instruction, value=self.value) return self if symbol.is_type(ValueType.NUMERIC): self.value = copy(symbol) if self.value.hex_len() == 2: return DirectOperand(self.operand_string, self.instruction, value=self.value) return ExtendedOperand(self.operand_string, self.instruction, value=self.value)
def test_fix_addresses_correct_for_valuetype_address(self): statement1 = Statement("START LDA #$00 ; load zero into A") statement1.set_address(0xFFEE) statement2 = Statement(" JMP START ; jump to start ") statement2.operand.value = AddressValue(0) statements = [statement1, statement2] statement2.fix_addresses(statements, 1) self.assertEqual("FFEE", statement2.code_pkg.additional.hex())
def test_fix_addresses_correct_for_reverse_branches(self): statement1 = Statement("START JSR $FFEE ; jump to subroutine") statement2 = Statement(" CLRA ; clear A") statement3 = Statement(" CLRA ; clear A") statement4 = Statement(" CLRA ; clear A") statement5 = Statement("DONE BRA START ; jump to start") statement1.code_pkg.size = 2 statement2.code_pkg.size = 1 statement3.code_pkg.size = 1 statement4.code_pkg.size = 1 statement5.code_pkg.size = 2 statement5.code_pkg.additional = AddressValue(0) statements = [ statement1, statement2, statement3, statement4, statement5 ] statement5.fix_addresses(statements, 4) self.assertEqual("F9", statement5.code_pkg.additional.hex())
def test_fix_addresses_correct_for_forward_branches(self): statement1 = Statement("START BRA DONE ; branch to done") statement2 = Statement(" CLRA ; clear A") statement3 = Statement(" CLRA ; clear A") statement4 = Statement(" CLRA ; clear A") statement5 = Statement("DONE JSR $FFEE ; jump to subroutine") statement1.code_pkg.additional = AddressValue(4) statement1.code_pkg.size = 2 statement2.code_pkg.size = 1 statement3.code_pkg.size = 1 statement4.code_pkg.size = 1 statement5.code_pkg.size = 2 statements = [ statement1, statement2, statement3, statement4, statement5 ] statement1.fix_addresses(statements, 0) self.assertEqual("03", statement1.code_pkg.additional.hex())
def save_symbol(self, index, statement): """ Checks a statement for a label and saves it to the symbol table, along with the index into the list of statements where the label occurs. Will raise a TranslationError if the label already exists in the symbol table. :param index: the index into the list of statements where the label occurs :param statement: the statement with the label """ label = statement.label if label: if label in self.symbol_table: raise TranslationError("Label [" + label + "] redefined", statement) if statement.instruction.is_pseudo_define: self.symbol_table[label] = statement.operand.value else: self.symbol_table[label] = AddressValue(index)
def test_symbol_byte_len_correct(self): result = AddressValue('16') self.assertEqual(1, result.byte_len())
def test_address_hex_len_correct(self): result = AddressValue('16') self.assertEqual(2, result.hex_len())
def test_address_str_correct(self): result = AddressValue('16') self.assertEqual("10", str(result))
def test_address_hex_correct(self): result = AddressValue('16') self.assertEqual("10", result.hex())
def test_address_ascii_works_correctly(self): result = AddressValue('11') self.assertEqual("11", result.ascii())