Example #1
0
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)
Example #2
0
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())
Example #3
0
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
Example #4
0
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)
Example #5
0
# 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())
Example #6
0
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)
Example #7
0
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
Example #8
0
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))
Example #9
0
# 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())