def self_codification_function(self): """ self_codification_function """ target = self.target instr = target.instructions[self.instr_name] repetition = 0 while repetition < REPETITIONS: values = [] for trial in range(0, TRIALS): try: print("Trial: %s" % trial) instruction = microprobe.code.ins.Instruction() instruction.set_arch_type(instr) for idx, operand in enumerate(instruction.operands()): if idx >= len(values): values.append(operand.type.random_value()) operand.set_value(values[idx]) codification = int(instruction.binary(), 2) print("Codification: 0x%x" % codification) print("Assembly: %s" % instruction.assembly()) instr_def = interpret_bin(hex(codification)[2:], target)[0] print("%s == %s ?" % (instr, instr_def.instruction_type)) self.assertEqual(instr.mnemonic, instr_def.instruction_type.mnemonic) for orig_operand, new_operand in zip(instruction.operands(), instr_def.operands): print("%s == %s ?" % (orig_operand.value, new_operand)) self.assertEqual(orig_operand.value, new_operand) break except (NotImplementedError, AssertionError) as exc: if trial == TRIALS - 1: raise exc repetition += 1 self.assertEqual(repetition, REPETITIONS)
def dump_bin(target, arguments): """ :param target: :type target: :param arguments: :type arguments: """ print_info("Parsing input file...") cmd = "od -Ax -tx1 -v '%s'" % arguments['input_bin_file'] text_string = run_cmd_output(cmd) bintext = [] for line in text_string.split('\n'): if line == "": continue bintext.append("".join(line.split(' ')[1:])) instrs = interpret_bin("".join(bintext), target, safe=arguments['safe']) for instr in instrs: print(instruction_from_definition(instr).assembly())
def generate(test_definition, output_file, target, **kwargs): """ Microbenchmark generation policy. :param test_definition: Test definition object :type test_definition: :class:`MicroprobeTestDefinition` :param output_file: Output file name :type output_file: :class:`str` :param target: Target definition object :type target: :class:`Target` """ end_address_orig = None overhead = 0 if len(test_definition.dat_mappings) > 0: # # Assuming MPT generated from MAMBO full system # dat = target.get_dat(dat_map=test_definition.dat_mappings) dat.control['DAT'] = True for instr in test_definition.code: instr.address = dat.translate(instr.address, rev=True) # Address order might have changed after mapping test_definition.set_instruction_definitions( sorted(test_definition.code, key=lambda x: x.address) ) # remove not translated addresses (needed?) # variables = [var for var in test_definition.variables # if var.address != dat.translate(var.address, rev=True)] # test_definition.set_variables_definition(variables) for var in test_definition.variables: var.address = dat.translate(var.address, rev=True) # Address order might have changed after mapping test_definition.set_variables_definition( sorted(test_definition.variables, key=lambda x: x.address) ) if test_definition.default_code_address != 0: test_definition.default_code_address = dat.translate( test_definition.default_code_address, rev=True ) if test_definition.default_data_address != 0: test_definition.default_data_address = dat.translate( test_definition.default_data_address, rev=True ) for access in test_definition.roi_memory_access_trace: access.address = dat.translate( access.address, rev=True ) if 'raw_bin' in kwargs: print_info("Interpreting RAW dump...") sequence = [] raw_dict = {} current_address = 0 # Assume state file provides the initial code address displ = test_definition.default_code_address test_definition.set_default_code_address(0) for entry in test_definition.code: if (not entry.assembly.upper().startswith("0X") and not entry.assembly.upper().startswith("0B")): raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "assembly (%s)" % entry.assembly ) if entry.label is not None: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "labels (%s)" % entry.label ) if entry.decorators not in ['', ' ', None, []]: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "decorators (%s)" % entry.decorators ) if entry.comments not in ['', ' ', None, []]: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "comments (%s)" % entry.comments ) if entry.address is not None: current_address = entry.address + displ if current_address not in raw_dict: raw_dict[current_address] = "" # Assume that raw dump use a 4 bytes hex dump if len(entry.assembly) != 10: raise MicroprobeMPTFormatError( "This is not a RAW 4-byte dump as it contains " "lines with other formats (%s)" % entry.assembly ) raw_dict[current_address] += entry.assembly[2:] if len(raw_dict) > 1: address_ant = sorted(raw_dict.keys())[0] len_ant = len(raw_dict[address_ant])//2 # Assume that raw dump use a 4 bytes hex dump assert len_ant % 4 == 0 for address in sorted(raw_dict.keys())[1:]: if address_ant + len_ant == address: raw_dict[address_ant] += raw_dict[address] len_ant = len(raw_dict[address_ant])//2 raw_dict.pop(address) else: len_ant = len(raw_dict[address])//2 address_ant = address # Assume that raw dump use a 4 bytes hex dump assert len_ant % 4 == 0 sequence = [] for address in sorted(raw_dict.keys()): # Endianess will be big endian, because we are concatenating # full words resulting in the higher bits being encoded first code = interpret_bin( raw_dict[address], target, safe=True, little_endian=False, word_length=4 ) for instr in code: instr.address = address instr = instruction_from_definition(instr) address = address + instr.architecture_type.format.length instr = instruction_to_asm_definition(instr) sequence.append(instr) test_definition.set_instruction_definitions(sequence) reset_steps = [] if 'no_wrap_test' not in kwargs: if test_definition.default_code_address != 0: print_error("Default code address should be zero") exit(-1) print_info("Wrapping function...") start_symbol = "START_TEST" init_address = test_definition.default_code_address for register in test_definition.registers: if register.name == "PC": init_address = register.value if register.name == "PSW_ADDR": init_address = register.value displacements = [] for elem in test_definition.code: if elem.address is not None: if len(displacements) == 0: displacements.append( (elem.address, 4*1024, elem.address - init_address) ) else: displacements.append( (elem.address, elem.address - displacements[-1][0], elem.address - init_address) ) # Get ranges with enough space to put init code # Assuming 4K space is enough displacements = [ displ for displ in displacements if displ[1] >= 4*1024 and displ[2] <= 0 ] if len(displacements) == 0: print_error( "Unable to find space for the initialization code. " "Check the mpt initial code address or state of PC " "for correctness." ) exit(-1) displ_fixed = False if kwargs['fix_start_address']: displacement = kwargs['fix_start_address'] print_info("Start point set to 0x%X" % displacement) displ_fixed = True elif 'fix_long_jump' in kwargs: displacement = sorted(displacements, key=lambda x: x[0])[0][0] if displacement > 2**32: displacement = 0x1000000 print_info("Start point set to 0x%X" % displacement) displ_fixed = True else: displacement = sorted(displacements, key=lambda x: x[2])[-1][0] start_symbol = None init_found = False for instr in test_definition.code: if instr.address == init_address: if instr.label is None: instr.label = "START_TEST" start_symbol = instr.label init_found = True break if not init_found: print_error( "Initial instruction address (%s) not found" % hex(init_address) ) exit(-1) if start_symbol is None: if test_definition.code[0].label is None: test_definition.code[0].label = "START_TEST" start_symbol = test_definition.code[0].label if displacement is None: displacement = 0 instructions = [] reset_steps = [] if 'wrap_endless' in kwargs and 'reset' in kwargs: target.scratch_var.set_address( Address( base_address=target.scratch_var.name ) ) new_ins, overhead, reset_steps = _compute_reset_code( target, test_definition, kwargs, ) instructions += new_ins if 'fix_long_jump' in kwargs: instructions += target.function_call( init_address, long_jump=True ) else: instructions += target.function_call( ("%s" % start_symbol).replace("+0x-", "-0x"), ) if 'wrap_endless' not in kwargs: instructions += [target.nop()] else: instructions += _compute_reset_jump(target, instructions) instructions_definitions = [] for instruction in instructions: instruction.set_label(None) if not displ_fixed: displacement = (displacement - instruction.architecture_type.format.length) current_instruction = MicroprobeAsmInstructionDefinition( instruction.assembly(), None, None, None, instruction.comments, ) instructions_definitions.append(current_instruction) instruction = target.nop() instruction.set_label(None) if not displ_fixed: displacement = (displacement - instruction.architecture_type.format.length) # To avoid overlaps if not displ_fixed: align = 0x100 displacement = ((displacement // align) + 0) * align instructions_definitions[0].address = displacement assert instructions_definitions[0].address is not None # instr = MicroprobeAsmInstructionDefinition( # instruction.assembly(), "ELF_ABI_EXIT", None, None, None) # end_address_orig = \ # (test_definition.default_code_address + displacement_end - # instruction.architecture_type.format.length) instructions_definitions[0].label = "mpt2elf_endless" test_definition.register_instruction_definitions( instructions_definitions, prepend=True, ) assert test_definition.code[0].address is not None if not displ_fixed: test_definition.set_default_code_address( test_definition.default_code_address + displacement, ) for elem in test_definition.code: if elem.address is not None: elem.address = elem.address - displacement else: test_definition.set_default_code_address( displacement ) for elem in test_definition.code: if elem.address is not None: elem.address = elem.address - displacement variables = test_definition.variables variables = [var for var in test_definition.variables if var.address is None or var.address >= 0x00100000] test_definition.set_variables_definition(variables) print_info("Interpreting asm ...") sequence_orig = interpret_asm( test_definition.code, target, [var.name for var in variables] + [target.scratch_var.name], show_progress=True, ) if len(sequence_orig) < 1: raise MicroprobeMPTFormatError( "No instructions found in the 'instructions' entry of the MPT" " file. Check the input file.", ) raw = test_definition.raw raw['FILE_FOOTER'] = "# mp_mpt2elf: Wrapping overhead: %03.2f %%" \ % overhead # end_address = end_address_orig ckwargs = { # 'end_address': end_address, # 'reset': False, # 'endless': 'endless' in kwargs } wrapper_name = "AsmLd" if test_definition.default_data_address is not None: ckwargs['init_data_address'] = \ test_definition.default_data_address if test_definition.default_code_address is not None: ckwargs['init_code_address'] = \ test_definition.default_code_address try: code_wrapper = microprobe.code.get_wrapper(wrapper_name) except MicroprobeValueError as exc: raise MicroprobeException( "Wrapper '%s' not available. Check if you have the wrappers" " of the target installed or set up an appropriate " "MICROPROBEWRAPPERS environment variable. Original error " "was: %s" % (wrapper_name, str(exc)), ) wrapper = code_wrapper(**ckwargs) print_info("Setup synthesizer ...") synthesizer = microprobe.code.Synthesizer( target, wrapper, no_scratch=False, extra_raw=raw, ) variables = test_definition.variables registers = test_definition.registers sequence = sequence_orig if len(registers) >= 0: cr_reg = [ register for register in registers if register.name == "CR" ] registers = [ register for register in registers if register.name != "CR" ] if cr_reg: value = cr_reg[0].value for idx in range(0, 8): cr = MicroprobeTestRegisterDefinition( "CR%d" % idx, (value >> (28 - (idx * 4))) & 0xF, ) registers.append(cr) synthesizer.add_pass( microprobe.passes.initialization.InitializeRegistersPass( registers, skip_unknown=True, warn_unknown=True, skip_control=True, force_reserved=True ), ) synthesizer.add_pass( microprobe.passes.structure.SimpleBuildingBlockPass( len(sequence), ), ) synthesizer.add_pass( microprobe.passes.variable.DeclareVariablesPass( variables, ), ) synthesizer.add_pass( microprobe.passes.instruction.ReproduceSequencePass(sequence), ) if target.name.startswith("power"): fix_branches = [instr.name for instr in target.instructions.values() if instr.branch_conditional] if 'raw_bin' in kwargs: # We do not know what is code and what is data, so we safely # disable the asm generation and keep the values for orig in [21, 17, 19]: synthesizer.add_pass( microprobe.passes.instruction.DisableAsmByOpcodePass( fix_branches, 0, ifval=orig ) ) else: # We know what is code and what is data, so we can safely # fix the branch instructions for new, orig in [(20, 21), (16, 17), (18, 19)]: synthesizer.add_pass( SetInstructionOperandsByOpcodePass( fix_branches, 0, new, force=True, ifval=orig ) ) if kwargs.get("fix_memory_registers", False): kwargs["fix_memory_references"] = True if kwargs.get("fix_memory_references", False): print_info("Fix memory references: On") synthesizer.add_pass( microprobe.passes.memory.FixMemoryReferencesPass( reset_registers=kwargs.get("fix_memory_registers", False), ), ) synthesizer.add_pass( microprobe.passes.register.FixRegistersPass( forbid_writes=['GPR3'], ), ) if kwargs.get("fix_memory_registers", False): print_info("Fix memory registers: On") synthesizer.add_pass( microprobe.passes.register.NoHazardsAllocationPass(), ) if kwargs.get("fix_branch_next", False): print_info("Force branch to next: On") synthesizer.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass( force="fix_flatten_code" in kwargs, noinit=True ) ) synthesizer.add_pass( microprobe.passes.branch.BranchNextPass(force=True), ) if kwargs.get("fix_indirect_branches", False): print_info("Fix indirect branches: On") synthesizer.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass( noinit=True ), ) synthesizer.add_pass( microprobe.passes.branch.FixIndirectBranchPass(), ) if displ_fixed: synthesizer.add_pass( microprobe.passes.address.SetInitAddressPass(displacement) ) synthesizer.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass( noinit=True, init_from_first=not displ_fixed, ), ) synthesizer.add_pass( microprobe.passes.variable.UpdateVariableAddressesPass( ), ) synthesizer.add_pass( microprobe.passes.symbol.ResolveSymbolicReferencesPass( onlyraw=True ), ) print_info("Start synthesizer ...") bench = synthesizer.synthesize() # Save the microbenchmark synthesizer.save(output_file, bench=bench) print_info("'%s' generated!" % output_file) _compile(output_file, target, **kwargs) return
def _interpret_instr_def(instr_def, target, labels): """ :param instr_def: :type instr_def: :param target: :type target: :param labels: :type labels: """ LOG.debug("Start interpret_asm: '%s'", instr_def) if instr_def.assembly in _ASM_CACHE: instruction_type, operands = _ASM_CACHE[instr_def.assembly] operands = operands[:] elif instr_def.assembly.upper().startswith("0X"): binary_def = interpret_bin(instr_def.assembly[2:], target, fmt="hex") if len(binary_def) > 1: raise MicroprobeAsmError("More than one instruction parsed.") instruction_type = binary_def[0].instruction_type operands = binary_def[0].operands _ASM_CACHE[instr_def.assembly] = (instruction_type, operands) elif instr_def.assembly.upper().startswith("0B"): binary_def = interpret_bin(instr_def.assembly[2:], target, fmt="bin") if len(binary_def) > 1: raise MicroprobeAsmError("More than one instruction parsed.") instruction_type = binary_def[0].instruction_type operands = binary_def[0].operands _ASM_CACHE[instr_def.assembly] = (instruction_type, operands) else: asm_mnemonic = _extract_asm_mnemonic(instr_def.assembly) LOG.debug("Mnemonic: '%s'", asm_mnemonic) asm_operands = _extract_asm_operands(instr_def.assembly) LOG.debug("Operands: '%s'", asm_operands) # This is a work-around for RISC-V objdump implementation. # It does not dump negative numbers and the corresponding # absolute value is printed. Also a weird +1 needs to be added for idx, asm_operand in enumerate(asm_operands): if asm_operand.startswith("0XF") and len(asm_operand) == 18: nval = hex(int(twocs_to_int(int(asm_operand, 16), 64)) + 1).upper() instr_def = list(instr_def) instr_def[0] = instr_def[0].upper().replace(asm_operand, nval) instr_def = MicroprobeAsmInstructionDefinition(*instr_def) asm_operands[idx] = nval # End work-around asm_mnemonic, asm_operands = target.normalize_asm( asm_mnemonic, asm_operands) LOG.debug("Norm. mnemonic: '%s'", asm_mnemonic) LOG.debug("Norm. Operands: '%s'", asm_operands) instruction_types, asm_operands = _find_instr_with_mnemonic( asm_mnemonic, asm_operands, target) LOG.debug("Types detected: '%s'", [type_ins.name for type_ins in instruction_types]) instruction_type, operands = _extract_operands(instr_def.assembly, asm_operands, instruction_types, target, labels) _ASM_CACHE[instr_def.assembly] = (instruction_type, operands) address = _extract_address(instr_def.address) if instr_def.decorators in _DECORATOR_CACHE: decorators = copy.deepcopy(_DECORATOR_CACHE[instr_def.decorators]) else: decorators = _interpret_decorators(instr_def.decorators) _DECORATOR_CACHE[instr_def.decorators] = decorators label = None if instr_def.label is not None: label = instr_def.label.upper() LOG.debug("End interpret_asm: '%s'", instr_def) return microprobe.code.ins.MicroprobeInstructionDefinition( instruction_type, operands, label, address, instr_def.assembly, decorators, instr_def.comments)
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import absolute_import from __future__ import print_function import sys from microprobe.target import import_definition from microprobe.utils.bin import interpret_bin from microprobe.code.ins import instruction_from_definition from microprobe.utils.asm import interpret_asm target = import_definition(sys.argv[1]) print(sys.argv[2:]) for elem in sys.argv[2:]: instr_def = interpret_bin(elem, target)[0] instr = instruction_from_definition(instr_def) codification = int(instr.binary(), 2) assembly = instr.assembly() instr_def2 = interpret_asm(assembly, target, [])[0] print(hex(codification)) instr_def3 = interpret_bin(hex(codification)[2:], target)[0] instr2 = instruction_from_definition(instr_def2) instr3 = instruction_from_definition(instr_def3) assert instr.assembly() == instr2.assembly() assert instr2.assembly() == instr3.assembly() assert instr.binary() == instr2.binary() assert instr2.binary() == instr3.binary() print(instr3.assembly())
def dump_objdump(target, arguments): """ :param target: :type target: :param arguments: :type arguments: """ cmd = "'%s' -Ax -tx1 -v '%s'" % (arguments['od_bin'], arguments['input_bin_file']) text_string = run_cmd_output(cmd) bintext = [] for line in text_string.split('\n'): if line == "": continue bintext.append("".join(line.split(' ')[1:])) instrs = interpret_bin("".join(bintext), target) print("") print("%s:\tfile format raw %s" % (os.path.basename(arguments['input_bin_file']), target.isa.name)) print("") print("") print("Disassembly of section .raw:") print("") maxlen = max(len(instr.asm[2:]) for instr in instrs) if maxlen % 2 != 0: maxlen = maxlen + 1 maxlen += maxlen // 2 counter = arguments['start_address'] label_dict = RejectingOrderedDict() instr_dict = RejectingOrderedDict() for instr_def in instrs: instr = instruction_from_definition(instr_def, fix_relative=False) asm = instr.assembly().lower() relative = None absolute = None if instr.branch: for memoperand in instr.memory_operands(): if not memoperand.descriptor.is_branch_target: continue for operand in memoperand.operands: if operand.type.address_relative: relative = operand.value if operand.type.address_absolute: absolute = operand.value masm = instr_def.asm[2:] if len(masm) % 2 != 0: masm = "0" + masm binary = " ".join([str(masm)[i:i + 2] for i in range(0, len(masm), 2)]) label = None if counter == 0: label = ".raw" label_dict[counter] = label elif counter in label_dict: label = label_dict[counter] rtarget = None atarget = None if relative is not None or absolute is not None: if relative is not None: assert absolute is None if isinstance(relative, six.integer_types): target_addr = counter + relative rtarget = relative elif isinstance(relative, Address): target_addr = counter + relative.displacement rtarget = relative.displacement else: raise NotImplementedError if absolute is not None: assert relative is None if isinstance(absolute, six.integer_types): target_addr = absolute atarget = absolute elif isinstance(absolute, Address): target_addr = absolute.displacement atarget = absolute.displacement else: raise NotImplementedError if target_addr not in label_dict: label_dict[target_addr] = "branch_%x" % target_addr if target_addr in instr_dict: instr_dict[target_addr][2] = label_dict[target_addr] instr_dict[counter] = [binary, asm, label, rtarget, atarget] counter = counter + len(masm) // 2 str_format = "%8s:\t%-" + str(maxlen) + "s\t%s" addresses = [] for counter, values in instr_dict.items(): binary, asm, label, rtarget, atarget = values if label is not None: print("%016x <%s>:" % (counter, label)) cformat = str_format if rtarget is not None: cformat = str_format + "\t <%s>" % (label_dict[counter + rtarget]) elif atarget is not None: cformat = str_format + "\t <%s>" % (label_dict[atarget]) print(cformat % (hex(counter)[2:], binary, asm)) addresses.append(counter) error = False for key in label_dict.keys(): if key not in addresses: print_warning("Target address '%s' not in the objdump" % hex(key)) error = True if error and arguments['strict']: print_error("Check target addresses of relative branches") exit(-1)
def generate(test_definition, outputfile, target, **kwargs): """ Microbenchmark generation policy :param test_definition: Test definition object :type test_definition: :class:`MicroprobeTestDefinition` :param outputfile: Outputfile name :type outputfile: :class:`str` :param target: Target definition object :type target: :class:`Target` """ variables = test_definition.variables if 'raw_bin' in kwargs: print_info("Interpreting RAW dump...") sequence = [] raw_dict = {} current_address = 0 for entry in test_definition.code: if (not entry.assembly.upper().startswith("0X") and not entry.assembly.upper().startswith("0B")): raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "assembly (%s)" % entry.assembly) if entry.label is not None: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "labels (%s)" % entry.label) if entry.decorators not in ['', ' ', None, []]: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "decorators (%s)" % entry.decorators) if entry.comments not in ['', ' ', None, []]: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "comments (%s)" % entry.comments) if entry.address is not None: current_address = entry.address if current_address not in raw_dict: raw_dict[current_address] = "" # Assume that raw dump use a 4 bytes hex dump if len(entry.assembly) != 10: raise MicroprobeMPTFormatError( "This is not a RAW 4-byte dump as it contains " "lines with other formats (%s)" % entry.assembly) raw_dict[current_address] += entry.assembly[2:] if len(raw_dict) > 1: address_ant = sorted(raw_dict.keys())[0] len_ant = len(raw_dict[address_ant]) // 2 # Assume that raw dump use a 4 bytes hex dump assert len_ant % 4 == 0 for address in sorted(raw_dict.keys())[1:]: if address_ant + len_ant == address: raw_dict[address_ant] += raw_dict[address] len_ant = len(raw_dict[address_ant]) // 2 raw_dict.pop(address) else: len_ant = len(raw_dict[address]) // 2 address_ant = address # Assume that raw dump use a 4 bytes hex dump assert len_ant % 4 == 0 sequence = [] for address in sorted(raw_dict.keys()): # Endianess will be big endian, because we are concatenating # full words resulting in the higher bits being encoded first code = interpret_bin(raw_dict[address], target, safe=True, little_endian=False, word_length=4) code[0].address = address sequence.extend(code) else: print_info("Interpreting assembly...") sequence = interpret_asm(test_definition.code, target, [var.name for var in variables]) if len(sequence) < 1: raise MicroprobeMPTFormatError( "No instructions found in the 'instructions' entry of the MPT" " file. Check the input file.") registers = test_definition.registers raw = test_definition.raw for instruction_def in sequence: if instruction_def.address is not None: print_warning("Instruction address not needed in '%s'" % instruction_def.asm) if test_definition.default_data_address is not None: print_warning("Default data address not needed") if test_definition.default_code_address is not None: print_warning("Default code address not needed") wrapper_name = "CWrapper" if kwargs.get("endless", False): print_warning("Using endless C wrapper") wrapper_name = "CInfGen" print_info("Creating benchmark synthesizer...") try: cwrapper = microprobe.code.get_wrapper(wrapper_name) except MicroprobeValueError as exc: raise MicroprobeException( "Wrapper '%s' not available. Check if you have the wrappers " "of the target installed or set up an appropriate " "MICROPROBEWRAPPERS environment variable. Original error was: %s" % (wrapper_name, str(exc))) wrapper_kwargs = {} wrapper = cwrapper(**wrapper_kwargs) synth = microprobe.code.Synthesizer(target, wrapper, extra_raw=raw) if len(registers) >= 0: print_info("Add register initialization pass") synth.add_pass( microprobe.passes.initialization.InitializeRegistersPass( registers, skip_unknown=True, warn_unknown=True)) synth.add_pass( microprobe.passes.structure.SimpleBuildingBlockPass(len(sequence))) synth.add_pass(microprobe.passes.variable.DeclareVariablesPass(variables)) synth.add_pass( microprobe.passes.instruction.ReproduceSequencePass(sequence)) if kwargs.get("fix_indirect_branches", False): print_info("Fix indirect branches: On") synth.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass()) synth.add_pass(microprobe.passes.branch.FixIndirectBranchPass()) if kwargs.get("fix_branch_next", False): print_info("Force branch to next: On") synth.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass()) synth.add_pass(microprobe.passes.branch.BranchNextPass(force=True)) if kwargs.get("fix_memory_registers", False): kwargs["fix_memory_references"] = True if kwargs.get("fix_memory_references", False): synth.add_pass( microprobe.passes.memory.FixMemoryReferencesPass( reset_registers=kwargs.get("fix_memory_registers", False))) if kwargs.get("fix_memory_registers", False): print_info("Fix memory registers: On") synth.add_pass(microprobe.passes.register.NoHazardsAllocationPass()) print_info("Synthesizing...") bench = synth.synthesize() # Save the microbenchmark synth.save(outputfile, bench=bench) return
def dump_objdump(target, arguments): """ :param target: :type target: :param arguments: :type arguments: """ ifile = open(arguments['input_dma_file'], 'r') dataw = arguments['width_bytes'] inputlines = ifile.readlines() ifile.close() progress = Progress(len(inputlines), msg="Lines parsed:") lines_dict = {} for idx, line in enumerate(inputlines): splitline = line.upper().split(" ") if len(splitline) != 3: raise MicroprobeDMAFormatError("Unable to parse line %d: %s" % (idx, line)) if (splitline[0] != "D" or len(splitline[1]) != 16 or len(splitline[1]) != 16): raise MicroprobeDMAFormatError("Unable to parse line %d: %s" % (idx, line)) key = int(splitline[1], base=16) if key in lines_dict: print_warning("Address (%s) in line %d overwrites previous entry" % (splitline[1], idx)) lines_dict[key] = splitline[2][:-1] progress() current_key = None progress = Progress(len(list(lines_dict.keys())), msg="Detecting segments:") for key in sorted(lines_dict): progress() if current_key is None: current_key = key continue current_address = current_key + (len(lines_dict[current_key]) // 2) if current_address == key: lines_dict[current_key] += lines_dict[key] lines_dict.pop(key) else: current_key = key instrs = [] progress = Progress(len(list(lines_dict.keys())), msg="Interpreting segments:") for key in sorted(lines_dict): progress() current_instrs = interpret_bin(lines_dict[key], target, safe=not arguments['strict']) current_instrs[0].address = Address(base_address='code', displacement=key) instrs += current_instrs maxlen = max([ins.format.length for ins in target.instructions.values()] + [dataw]) * 2 maxlen += maxlen // 2 counter = 0 label_dict = RejectingDict() instr_dict = RejectingDict() range_num = 1 progress = Progress(len(instrs), msg="Computing labels:") for instr_def in instrs: progress() if instr_def.address is not None: counter = instr_def.address.displacement if instr_def.instruction_type is None: for idx in range(0, len(instr_def.asm), dataw * 2): label = None if instr_def.address is not None and idx == 0: label = ".range_%x" % range_num label_dict[counter] = label range_num += 1 elif counter in label_dict: label = label_dict[counter] idx2 = min(idx + (dataw * 2), len(instr_def.asm)) masm = instr_def.asm[idx:idx2].lower() binary = " ".join([ str(masm)[i:i + 2] for i in range(0, len(masm), 2) ]).lower() instr_dict[counter] = [binary, "0x" + masm, label, None, None] counter += (idx2 - idx) // 2 continue instr = instruction_from_definition(instr_def, fix_relative=False) asm = instr.assembly().lower() relative = None absolute = None if instr.branch: for memoperand in instr.memory_operands(): if not memoperand.descriptor.is_branch_target: continue for operand in memoperand.operands: if operand.type.address_relative: relative = operand.value if operand.type.address_absolute: absolute = operand.value masm = instr_def.asm[2:] if len(masm) % 2 != 0: masm = "0" + masm binary = " ".join([str(masm)[i:i + 2] for i in range(0, len(masm), 2)]) label = None if instr_def.address is not None: if counter not in label_dict: label = ".range_%x" % range_num label_dict[counter] = label range_num += 1 else: label = label_dict[counter] elif counter in label_dict: label = label_dict[counter] rtarget = None atarget = None if relative is not None or absolute is not None: if relative is not None: assert absolute is None if isinstance(relative, int): target_addr = counter + relative rtarget = relative elif isinstance(relative, Address): target_addr = counter + relative.displacement rtarget = relative.displacement else: raise NotImplementedError if absolute is not None: assert relative is None if isinstance(absolute, int): target_addr = absolute atarget = absolute elif isinstance(absolute, Address): target_addr = absolute.displacement atarget = absolute.displacement else: raise NotImplementedError if target_addr not in label_dict: label_dict[target_addr] = "branch_%x" % target_addr if target_addr in instr_dict: instr_dict[target_addr][2] = label_dict[target_addr] instr_dict[counter] = [binary, asm, label, rtarget, atarget] counter = counter + (len(masm) // 2) print("") print("%s:\tfile format raw %s" % (os.path.basename(arguments['input_dma_file']), target.isa.name)) print("") print("") print("Disassembly of section .code:") print("") str_format = "%8s:\t%-" + str(maxlen) + "s\t%s" for counter in sorted(instr_dict.keys()): binary, asm, label, rtarget, atarget = instr_dict[counter] if label is not None: print("%016x <%s>:" % (counter, label)) cformat = str_format if rtarget is not None: cformat = str_format + "\t <%s>" % (label_dict[counter + rtarget]) elif atarget is not None: cformat = str_format + "\t <%s>" % (label_dict[atarget]) print(cformat % (hex(counter)[2:], binary, asm))
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import absolute_import from __future__ import print_function import sys from microprobe.target import import_definition from microprobe.utils.bin import interpret_bin from microprobe.code.ins import instruction_from_definition from microprobe.utils.asm import interpret_asm target = import_definition(sys.argv[1]) print(sys.argv[2:]) for elem in sys.argv[2:]: instr_def = interpret_bin(elem, target, single=True)[0] instr = instruction_from_definition(instr_def) codification = int(instr.binary(), 2) assembly = instr.assembly() instr_def2 = interpret_asm(assembly, target, [])[0] print(hex(codification)) instr_def3 = interpret_bin(hex(codification)[2:], target, single=True)[0] instr2 = instruction_from_definition(instr_def2) instr3 = instruction_from_definition(instr_def3) assert instr.assembly() == instr2.assembly() assert instr2.assembly() == instr3.assembly() assert instr.binary() == instr2.binary() assert instr2.binary() == instr3.binary() print(instr3.assembly())