def test_signed_value_to_tryte(): expected_output = "MMM" test_output = handle_instr.signed_value_to_tryte(-9841) assert (test_output == expected_output) expected_output = "d0A" test_output = handle_instr.signed_value_to_tryte(2915) assert (test_output == expected_output)
def handle_function_calls(assembled_code_dict, fn_start_dict): """ Loop through function bodies, find all CALL $func placeholders and replace them with actual addresses. """ new_assembled_code = dict() for fn_name in assembled_code_dict: new_assembled_fn = [] for assembled_statement in assembled_code_dict[fn_name]: if assembled_statement[0][0] == "CALL": referenced_fn_name = assembled_statement[0][1][1:] referenced_fn_addr = fn_start_dict[referenced_fn_name] referenced_fn_addr = handle_instr.signed_value_to_tryte( referenced_fn_addr) new_assembled_statement = [[]] new_assembled_statement[0].append( "0jm") # replace call with jump and store new_assembled_statement[0].append(referenced_fn_addr) new_assembled_statement.append(2) new_assembled_fn.append(new_assembled_statement) else: new_assembled_fn.append(assembled_statement) new_assembled_code[fn_name] = new_assembled_fn return new_assembled_code
def handle_jump_instructions(assembled_code_list): """ Handle labels left by jump statements. """ # first traverse lists looking for !jump destination labels # and store their locations new_assembled_code_list = [] assembled_code_length = 0 jump_label_dict = dict() for statement in assembled_code_list: if statement[-1] == 0: # statement has no assembled length, must be a jump label jump_label_dict[statement[0][0][1:]] = assembled_code_length else: # a normal instruction, add it to our new list and update length new_assembled_code_list.append(statement) assembled_code_length += statement[-1] # now search for jump instructions and assemble them, attaching their # destinations in jump_label_dict assembled_code_list = [statement for statement in new_assembled_code_list] new_assembled_code_list = [] for statement in assembled_code_list: instr = statement[0][0] if instr[:2] == "JP": new_statement = [] jump_label = statement[0][1] dest = jump_label_dict.get(jump_label) if dest is None: print("No matching jump destination label for {}.".format( jump_label)) sys.exit(1) new_statement.append(statement[0]) if len(instr) == 2: # found a JP instruction new_statement[0][0] = "0jj" elif instr[2] == "Z": # found a JPZ instruction new_statement[0][0] = "0j0" elif instr[2] == "P": # found a JPP instruction new_statement[0][0] = "0ja" elif instr[2] == "N": # found a JPN instruction new_statement[0][0] = "0jA" elif instr[2] == "S": # found a JPS instruction new_statement[0][0] = "0jm" else: print("Unrecognised jump opcode - aborting...") sys.exit(1) new_statement[0][1] = handle_instr.signed_value_to_tryte(dest) new_statement.append(statement[-1]) new_assembled_code_list.append(new_statement) else: new_assembled_code_list.append(statement) return new_assembled_code_list
def test_SWAP_trints(): for trint1 in test_trint_registers: for trint2 in test_trint_registers: reg1_pos = test_trint_register_names.find(trint1) reg2_pos = test_trint_register_names.find(trint2) num = 9 * reg1_pos + reg2_pos opcode = handle_instr.signed_value_to_tryte(num + 4 * 81 - 40) opcode = "j" + opcode[1:] expected_output = [[opcode], 1] test_output = assemble.assemble_instr(["SWAP", trint1, trint2, 98]) assert (test_output == expected_output)
def test_DIV_floats(): for tfloat1 in test_float_registers: for tfloat2 in test_float_registers: reg1_pos = test_float_register_names.index(tfloat1) reg2_pos = test_float_register_names.index(tfloat2) num = 9 * reg1_pos + reg2_pos opcode = handle_instr.signed_value_to_tryte(num - 0 * 81 - 40) opcode = "f" + opcode[1:] expected_output = [[opcode], 1] test_output = assemble.assemble_instr( ["DIV", tfloat1, tfloat2, 289]) assert (test_output == expected_output)