Esempio n. 1
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """

        addresses_set = []

        context = building_block.context

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:

                # if not instr.hfp_exponent_overflow_exception:
                #    continue

                if not instr.decimal:
                    continue

                for memoperand in instr.memory_operands():

                    if memoperand.address is None:
                        continue

                    if memoperand.address in addresses_set:
                        continue

                    if memoperand.is_load:

                        # Set a correct value in that address
                        assert memoperand.length > 0

                        # Step4: store the content to the target
                        instrs = target.store_decimal(
                            memoperand.address, memoperand.length, self._value,
                            context
                        )

                        context.set_memory_value(
                            MemoryValue(
                                memoperand.address, self._value,
                                memoperand.length
                            )
                        )

                        addresses_set.append(memoperand.address)
                        building_block.add_init(instrs)
Esempio n. 2
0
    def __init__(self, value=0):
        """

        :param value:  (Default value = 0)

        """
        super(InitializeMemoryFloatPass, self).__init__()
        self._var = microprobe.code.var.VariableSingle("FP_INITVAL",
                                                       "double",
                                                       value="%.20f" % value)
        self._varaddress = Address(base_address=self._var)

        self._value = value
        self._memvalue = MemoryValue(self._varaddress, value, 8)
        self._description = "Initialize all the memory location accessed by" \
                            " binary floating point operations to value: '%s'"\
                            "." % (self._value)
Esempio n. 3
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """

        variable_to_declare = False
        addresses_set = []
        context = building_block.context

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:

                # if not instr.hfp_exponent_overflow_exception:
                #    continue

                is_float = False
                for operand in instr.operands():

                    if operand.type.float and operand.is_input:
                        is_float = True

                if not is_float:
                    continue

                for memoperand in instr.memory_operands():

                    if memoperand.address is None:
                        continue

                    if memoperand.address in addresses_set:
                        continue

                    if memoperand.is_load:

                        if variable_to_declare is False:

                            variable_to_declare = True

                            reg2 = target.get_register_for_address_arithmetic(
                                context)

                            instrs = target.set_register(
                                reg2, ieee_float_to_int64(self._value),
                                context)

                            building_block.add_init(instrs)

                            context.set_register_value(
                                reg2, ieee_float_to_int64(self._value))

                            context.add_reserved_registers([reg2])

                            reg1 = target.get_register_for_address_arithmetic(
                                context)

                            context.add_reserved_registers([reg1])

                        instrs = target.set_register_to_address(
                            reg1, memoperand.address, context)

                        context.set_register_value(reg1, memoperand.address)

                        instrs += target.store_integer(reg2,
                                                       memoperand.address, 64,
                                                       context)

                        context.set_memory_value(
                            MemoryValue(memoperand.address, self._value, 8))

                        addresses_set.append(memoperand.address)

                        building_block.add_init(instrs)

                        LOG.debug("Instruction: %s: %s", instr.address, instr)
                        LOG.debug("Address: %s", memoperand.address)

        if variable_to_declare:
            context.remove_reserved_registers([reg1, reg2])
Esempio n. 4
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """

        descriptors = {}
        context = building_block.context

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:

                if instr.switching == "None":
                    if self._strict:
                        raise MicroprobeCodeGenerationError(
                            "No switching defined for '%s'" % instr
                        )
                    LOG.warning("No switching defined for '%s'", instr)
                    continue

                if instr.architecture_type not in descriptors:

                    LOG.debug("Initializing switching for '%s'", instr)

                    statuses = []
                    for status in instr.switching:
                        statuses.append(status)

                    status_idx = 0
                    repl_idx = 0

                    output_registers = [None] * self._replicate

                    for idx in range(0, self._replicate):
                        for operand in instr.operands():
                            if operand.is_output:

                                assert output_registers[idx] is None

                                if statuses[0][0] == "None":
                                    continue
                                try:

                                    output_registers[idx] = \
                                        [reg for reg in
                                         operand.type.values() if reg not in
                                         context.reserved_registers][0]

                                except IndexError:

                                    LOG.critical(
                                        [reg for reg in operand.type.values()
                                         if reg not in
                                         context.reserved_registers])

                                    LOG.critical(operand)
                                    LOG.critical(building_block.context.dump())
                                    raise NotImplementedError

                                context.add_reserved_registers(
                                    operand.type.access(output_registers[idx])
                                )

                                building_block.add_init(
                                    target.set_register(
                                        output_registers[idx], statuses[0][
                                            0
                                        ], building_block.context
                                    )
                                )

                                building_block.context.set_register_value(
                                    output_registers[idx], statuses[0][0]
                                )

                                LOG.debug(
                                    "Output register set to '%x'",
                                    statuses[0][0]
                                )

                    LOG.debug("Output registers: %s", output_registers)
                    LOG.debug("Statuses: %s", statuses)
                    LOG.debug("Index: %d", status_idx)
                    LOG.debug("Replication Index: %d", repl_idx)

                    descriptors[instr.architecture_type] = \
                        (output_registers, status_idx, repl_idx,
                         statuses * self._replicate, 1)

                else:

                    output_registers, status_idx, repl_idx, statuses, count = \
                        descriptors[instr.architecture_type]

                    descriptors[instr.architecture_type] = \
                        (output_registers, status_idx,
                         repl_idx, statuses, count + 1)

        for key, values in descriptors.items():

            output_registers, status_idx, repl_idx, statuses, count = values
            descriptors[key] = (
                output_registers, status_idx, repl_idx, statuses, count
            )

        LOG.debug("Setting up switching")

        for bbl in building_block.cfg.bbls:

            for instr in bbl.instrs:

                LOG.debug("Instruction: '%s'", instr)

                if instr.switching == "None":
                    LOG.debug("No switching defined for '%s'", instr)
                    continue

                if len(
                    [
                        oper for oper in instr.operands() if oper.value is None
                    ]
                ) == 0:
                    LOG.debug(
                        "Operands of the instructions already set '%s'", instr
                    )
                    continue

                output_registers, status_idx, repl_idx, statuses, count = \
                    descriptors[instr.architecture_type]

                output_register = output_registers[repl_idx]

                if count == 0 and statuses[0][0] != "None":
                    LOG.debug(
                        "Skip last switch if not pair to maintain "
                        "switching effects"
                    )
                    LOG.debug("Current count: %s", count)

                    LOG.critical(
                        instr.architecture_type, count, repl_idx, status_idx,
                        len(statuses)
                    )

                    # TODO: add strict/not strict parameter
                    exit(0)

                if output_register is not None:
                    instr.add_allow_register(output_register)

                status = statuses[
                    repl_idx * (len(statuses) // self._replicate) + status_idx
                ]

                LOG.debug("Current descriptor:")
                LOG.debug("Output register: %s", output_register)
                LOG.debug("Statuses: %s", statuses)
                LOG.debug("Index: %d", status_idx)
                LOG.debug("Replication Index: %d", repl_idx)
                LOG.debug("Current status: %s", status)
                LOG.debug("Current count: %s", count)

                memoperand_idx = 0
                memoperand_list = [
                    memop
                    for memop in instr.memory_operands()
                    if memop.address is not None
                ]

                operand_idx = 0
                operand_list = [
                    oper
                    for oper in instr.operands()
                    if oper.value is None and oper.is_input and
                    not oper.type.constant
                ]

                # if len(operand_list) == 0:
                #    for oper in instr.operands():
                #        LOG.debug(oper)
                #    raise MicroprobeCodeGenerationError(
                #        "No operand to switch. All already set?"
                #    )

                LOG.debug("Switching instruction: %s", instr)
                LOG.debug("Operands to switch:")
                for oper in operand_list:
                    LOG.debug(oper)

                for switch_input in status[1:]:

                    LOG.debug("Init value to set: %s", switch_input)
                    LOG.debug("Operand idx: %d", operand_idx)

                    if switch_input == "None":
                        # Nothing to do. Assume a register or immediate
                        LOG.debug("Skip")
                        operand_idx += 1

                    elif isinstance(switch_input, str) and \
                            switch_input.startswith("Mem:"):

                        # Memory
                        LOG.debug("Memory operand")

                        memoperand = memoperand_list[memoperand_idx]
                        address = memoperand.address

                        required_value = switch_input.split(":")[1]
                        LOG.debug("Raw required value %s", str(required_value))
                        if "_" in required_value:
                            size = int(required_value.split("_")[1], 10)
                            required_value = required_value.split("_")[0]
                            prefix = ""
                            if required_value.upper().startswith("0X"):
                                prefix = "0x"
                                required_value = required_value[2:]
                            elif required_value.upper().startswith("0B"):
                                prefix = "0b"
                                required_value = required_value[2:]

                            opsize = memoperand.length * 8
                            assert opsize % size == 0
                            mult = int(opsize / size)
                            required_value = prefix + required_value * mult
                            required_value = int(required_value, 0)
                        else:
                            required_value = int(required_value, 0)

                        # we can modify a bit the address if we maintain the
                        # same cache line

                        # linesize = target.cache_hierarchy.data_linesize()
                        memory_set = False
                        # for displacement in range(
                        #    0, linesize / 8, memoperand.length
                        # ):

                        for displacement in [0]:

                            address = address + displacement
                            memvalue = building_block.context.get_memory_value(
                                address
                            )

                            LOG.debug("Required value: 0x%x", required_value)
                            LOG.debug("Target address: %s", address)
                            LOG.debug("Current memory value: %s", memvalue)

                            if memvalue is None:

                                LOG.debug("Initialize memory contents")

                                mycontext = target.wrapper.context()
                                treg = target.scratch_registers[0]
                                instrs = target.set_register(
                                    treg, required_value,
                                    mycontext
                                )
                                areg = target.scratch_registers[1]
                                instrs += target.set_register_to_address(
                                    areg, address,
                                    mycontext
                                )
                                mycontext.set_register_value(
                                    areg, address
                                )

                                reg0 = \
                                    target.get_register_for_address_arithmetic(
                                        mycontext
                                    )
                                instrs += target.set_register(
                                    reg0, 0,
                                    mycontext
                                )
                                mycontext.set_register_value(
                                    reg0, 0
                                )

                                instrs += target.store_integer(
                                    treg, address, memoperand.length * 8,
                                    mycontext
                                )

                                building_block.add_init(instrs, prepend=True)
                                building_block.context.set_memory_value(
                                    MemoryValue(
                                        address, required_value,
                                        memoperand.length
                                    )
                                )

                                # memoperand.set_address(
                                #    address, building_block.context
                                # )

                                LOG.debug("Memory contents initialized")
                                memory_set = True
                                break

                            elif memvalue.value == required_value and \
                                    memvalue.length == memoperand.length:

                                # perfect, nothing to do
                                LOG.debug(
                                    "Memory contents already contain the"
                                    " required value."
                                )

                                # memoperand.set_address(
                                #     address, building_block.context
                                # )

                                memory_set = True
                                break

                        if memory_set is False:

                            LOG.warning(
                                "Unable to set the memory to the"
                                " required value."
                            )

                        memoperand_idx += 1

                    else:

                        operand = operand_list[operand_idx]
                        LOG.debug("Operand: %s", operand)

                        if isinstance(switch_input, str):
                            LOG.debug(
                                "Required value before: %s", switch_input
                            )

                            if "_" in switch_input:
                                size = int(switch_input.split("_")[1], 10)
                                switch_input = switch_input.split("_")[0]
                                prefix = ""
                                if switch_input.upper().startswith("0X"):
                                    prefix = "0x"
                                    switch_input = switch_input[2:]
                                elif switch_input.upper().startswith("0B"):
                                    prefix = "0b"
                                    switch_input = switch_input[2:]

                                if operand.type.immediate:
                                    raise MicroprobeCodeGenerationError(
                                        "No support for immediate definition "
                                        "with '_'. Provide the full value."
                                    )
                                else:
                                    opsize = \
                                        operand.type.random_value().type.size
                                    assert opsize % size == 0
                                    mult = int(opsize / size)
                                    switch_input = prefix + switch_input * mult

                            switch_input = int(switch_input, 0)
                            LOG.debug("Required value: %s", switch_input)

                        if operand.is_output:
                            LOG.debug(
                                "Operand is output. Already fixed to "
                                "'%s' ", output_register
                            )
                            operand.set_value(output_register)

                        elif operand.type.immediate:
                            LOG.debug(
                                "Operand is immediate. Set to '%s' (0x%X)",
                                switch_input, switch_input
                            )
                            operand.set_value(switch_input)

                        elif building_block.context.register_has_value(
                            switch_input
                        ) and building_block.context.registers_get_value(
                                    switch_input
                                )[0] in operand.type.values():
                            treg = building_block.context.registers_get_value(
                                switch_input
                            )[0]

                            LOG.debug("Value already in register '%s'", treg)
                            operand.set_value(treg)

                        else:
                            LOG.debug("Initializing register contents")
                            tregs = [
                                reg
                                for reg in operand.type.values()
                                if reg not in context.reserved_registers
                            ]

                            if len(tregs) == 0:
                                # raise MicroprobeCodeGenerationError(
                                #    "No free registers available to switching"
                                # )
                                LOG.debug(
                                    "No free registers available to switching"
                                )
                            else:
                                treg = tregs[0]
                                instrs = target.set_register(
                                    treg, switch_input, context
                                )

                                operand.set_value(treg)
                                building_block.add_init(instrs)
                                building_block.context.set_register_value(
                                    treg, switch_input
                                )

                                building_block.context.add_reserved_registers(
                                    [reg for reg in operand.uses()
                                     if reg not in context.reserved_registers]
                                )

                                LOG.debug(
                                    "Register '%s' set to '%s'", treg,
                                    switch_input
                                )

                        operand_idx += 1

                repl_idx += 1
                repl_idx = repl_idx % self._replicate

                if repl_idx == 0:
                    status_idx += 1
                    status_idx = status_idx % (
                        len(statuses) // self._replicate)

                descriptors[instr.architecture_type] = \
                    (output_registers, status_idx, repl_idx, statuses,
                     count - 1)
Esempio n. 5
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """

        descriptors = {}
        context = building_block.context

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:

                if instr.switching == "None":
                    if self._strict:
                        raise MicroprobeCodeGenerationError(
                            "No switching defined for '%s'" % instr)
                    LOG.warning("No switching defined for '%s'", instr)
                    continue

                if instr.architecture_type not in descriptors:

                    LOG.debug("Initializing switching for '%s'", instr)

                    statuses = []
                    for status in instr.switching:
                        statuses.append(status)

                    status_idx = 0
                    repl_idx = 0

                    output_registers = [None] * self._replicate

                    for idx in range(0, self._replicate):
                        for operand in instr.operands():
                            if operand.is_output:

                                assert output_registers[idx] is None

                                if statuses[0][0] == "None":

                                    continue

                                try:

                                    output_registers[idx] = \
                                        [reg for reg in
                                         operand.type.values() if reg not in
                                         context.reserved_registers][0]

                                except IndexError:

                                    LOG.critical([
                                        reg for reg in operand.type.values() if
                                        reg not in context.reserved_registers
                                    ])

                                    LOG.critical(operand)
                                    LOG.critical(building_block.context.dump())
                                    raise NotImplementedError

                                context.add_reserved_registers(
                                    [output_registers[idx]])

                                building_block.add_init(
                                    target.set_register(
                                        output_registers[idx], statuses[0][0],
                                        building_block.context))

                                building_block.context.set_register_value(
                                    output_registers[idx], statuses[0][0])

                                LOG.debug("Output register set to '%x'",
                                          statuses[0][0])

                    LOG.debug("Output registers: %s", output_registers)
                    LOG.debug("Statuses: %s", statuses)
                    LOG.debug("Index: %d", status_idx)
                    LOG.debug("Replication Index: %d", repl_idx)

                    descriptors[instr.architecture_type] = \
                        (output_registers, status_idx, repl_idx,
                         statuses * self._replicate, 1)

                else:

                    output_registers, status_idx, repl_idx, statuses, count = \
                        descriptors[instr.architecture_type]

                    descriptors[instr.architecture_type] = \
                        (output_registers, status_idx,
                         repl_idx, statuses, count + 1)

        for key, values in descriptors.items():

            output_registers, status_idx, repl_idx, statuses, count = values
            descriptors[key] = (output_registers, status_idx, repl_idx,
                                statuses, count)

        LOG.debug("Setting up switching")

        for bbl in building_block.cfg.bbls:

            for instr in bbl.instrs:

                LOG.debug("Instruction: '%s'", instr)

                if instr.switching == "None":
                    LOG.debug("No switching defined for '%s'", instr)
                    continue

                if len([
                        oper for oper in instr.operands() if oper.value is None
                ]) == 0:
                    LOG.debug("Operands of the instructions already set '%s'",
                              instr)
                    continue

                output_registers, status_idx, repl_idx, statuses, count = \
                    descriptors[instr.architecture_type]

                output_register = output_registers[repl_idx]

                if count == 0 and statuses[0][0] != "None":
                    LOG.debug("Skip last switch if not pair to maintain "
                              "switching effects")
                    LOG.debug("Current count: %s", count)

                    LOG.critical(instr.architecture_type, count, repl_idx,
                                 status_idx, len(statuses))

                    # TODO: add strict/not strict parameter
                    exit(0)

                if output_register is not None:
                    instr.add_allow_register(output_register)

                status = statuses[repl_idx *
                                  (len(statuses) // self._replicate) +
                                  status_idx]

                LOG.debug("Current descriptor:")
                LOG.debug("Output register: %s", output_register)
                LOG.debug("Statuses: %s", statuses)
                LOG.debug("Index: %d", status_idx)
                LOG.debug("Replication Index: %d", repl_idx)
                LOG.debug("Current status: %s", status)
                LOG.debug("Current count: %s", count)

                memoperand_idx = 0
                memoperand_list = [
                    memop for memop in instr.memory_operands()
                    if memop.address is not None
                ]

                operand_idx = 0
                operand_list = [
                    oper for oper in instr.operands() if oper.value is None
                    and oper.is_input and not oper.type.constant
                ]

                for switch_input in status[1:]:

                    LOG.debug("Init: %s", switch_input)

                    if switch_input == "None":
                        # Nothing to do. Assume a register or immediate
                        operand_idx += 1

                    elif isinstance(switch_input, str) and \
                            switch_input.startswith("Mem:"):
                        # Memory
                        required_value = int(switch_input.split(":")[1], 0)
                        memoperand = memoperand_list[memoperand_idx]
                        address = memoperand.address

                        # we can modify a bit the address if we maintain the
                        # same cache line

                        # linesize = target.cache_hierarchy.data_linesize()
                        memory_set = False
                        # for displacement in range(
                        #    0, linesize / 8, memoperand.length
                        # ):

                        for displacement in [0]:

                            address = address + displacement
                            memvalue = building_block.context.get_memory_value(
                                address)

                            LOG.debug("Required value: 0x%x", required_value)
                            LOG.debug("Target address: %s", address)
                            LOG.debug("Current memory value: %s", memvalue)

                            if memvalue is None:
                                LOG.debug("Initialize memory contents")

                                treg = target.scratch_registers[0]

                                instrs = target.set_register(
                                    treg, required_value,
                                    building_block.context)

                                instrs += target.store_integer(
                                    treg, address, memoperand.length * 8,
                                    building_block.context)

                                building_block.add_init(instrs)
                                building_block.context.set_memory_value(
                                    MemoryValue(address, required_value,
                                                memoperand.length))

                                memoperand.set_address(address,
                                                       building_block.context)

                                LOG.debug("Memory contents initialized")
                                memory_set = True
                                break

                            elif memvalue.value == required_value and \
                                    memvalue.length == memoperand.length:

                                # perfect, nothing to do
                                LOG.debug("Memory contents already contain the"
                                          " required value.")

                                memoperand.set_address(address,
                                                       building_block.context)

                                memory_set = True
                                break

                        if memory_set is False:

                            LOG.warning("Unable to set the memory to the"
                                        " required value.")

                        memoperand_idx += 1

                    else:

                        LOG.debug("Required value: %s", switch_input)
                        operand = operand_list[operand_idx]
                        LOG.debug("Operand: %s", operand)

                        if operand.is_output:

                            LOG.debug(
                                "Operand is output. Already fixed to "
                                "'%s' ", output_register)
                            operand.set_value(output_register)

                        elif operand.type.immediate:

                            LOG.debug("Operand is immediate. Set to '%s'",
                                      switch_input)
                            operand.set_value(switch_input)

                        elif building_block.context.register_has_value(
                                switch_input):

                            treg = building_block.context.registers_get_value(
                                switch_input)[0]

                            LOG.debug("Value already in register '%s'", treg)
                            operand.set_value(treg)

                        else:

                            LOG.debug("Initializing register contents")
                            treg = [
                                reg for reg in operand.type.values()
                                if reg not in context.reserved_registers
                            ][0]

                            instrs = target.set_register(
                                treg, switch_input, context)

                            operand.set_value(treg)
                            building_block.add_init(instrs)
                            building_block.context.set_register_value(
                                treg, switch_input)
                            building_block.context.add_reserved_registers(
                                [treg])
                            LOG.debug("Register '%s' set to '%s'", treg,
                                      switch_input)

                        operand_idx += 1

                repl_idx += 1
                repl_idx = repl_idx % self._replicate

                if repl_idx == 0:
                    status_idx += 1
                    status_idx = status_idx % (len(statuses) //
                                               self._replicate)

                descriptors[instr.architecture_type] = \
                    (output_registers, status_idx, repl_idx, statuses,
                     count - 1)