Beispiel #1
0
        def _fix_field(string, base, dummy, field):
            field_names = [fld.name for fld in self.format.fields]
            if (string.find(base) > 0 and dummy in field_names
                    and field in field_names):
                assert _get_value(dummy, base) == "0"
                value = _get_value(field, base)

                if field == 'cu_imm5':
                    value = str(int_to_twocs(int(value), 20))

                return string.replace(base, str(value))
            else:
                return string
Beispiel #2
0
def _interpret_bin_instr(instr_type, bin_instr):
    """

    :param target:
    :type target:
    """
    LOG.debug("Interpret bin instr: %s, %s", instr_type, hex(bin_instr))

    operand_values = []
    processed_bits = 0
    for op_descriptor, field in zip(
        list(instr_type.operands.items()), instr_type.format.fields
    ):
        dummy_fieldname, op_descriptor = op_descriptor
        operand, dummy_io_def = op_descriptor

        processed_bits += field.size

        LOG.debug("Process field: %s, size: %d", field, field.size)
        LOG.debug("Process operand: %s", operand)
        LOG.debug("Processed bits: %d", processed_bits)

        if not field.default_show:
            LOG.debug("Skip, not shown")
            continue

        field_value = (
            bin_instr >> (
                (
                    (instr_type.format.length * 8) - processed_bits
                )
            )
        ) & (
            (0b1 << field.size) - 1
        )

        LOG.debug("All: 0x%x", bin_instr)
        LOG.debug(
            "Shift bits: %d", (instr_type.format.length * 8) - processed_bits
        )
        LOG.debug(
            "Shifted value: 0x%x", (
                bin_instr >> (
                    (
                        (instr_type.format.length * 8) - processed_bits
                    )
                )
            )
        )
        LOG.debug("Field size: %d", field.size)
        LOG.debug("Mask used: 0x%x", (0b1 << field.size) - 1)
        LOG.debug("Field value: %s", hex(field_value))
        LOG.debug("Field value: %s", bin(field_value))

        found = False
        if (operand.immediate or
                operand.address_relative or operand.address_absolute):

            LOG.debug("Immediate/Relative operand")
            oper_size_pairs = [(field_value, field.size, 0)]

            if operand.shift > 0:

                LOG.debug("Operand shifted by: %s", operand.shift)
                pair = (
                    field_value << operand.shift, field.size + operand.shift,
                    operand.shift
                )
                oper_size_pairs.append(pair)

            if hasattr(operand, "step"):

                LOG.debug("Operand has a step of: %s", operand.step)
                for idx in [0, 1, 2]:

                    if (int(math.log(operand.step, 2)) - idx) < 0:
                        continue

                    pair = (
                        field_value << (
                            int(math.log(operand.step, 2)) - idx
                        ), field.size + int(math.log(operand.step, 2)) - idx,
                        (int(math.log(operand.step, 2)) - idx)
                    )
                    oper_size_pairs.append(pair)

                if operand.shift > 0:

                    LOG.debug(
                        "Operand shifted/stepped: %s %s", operand.shift,
                        operand.step
                    )
                    pair = (
                        field_value << (
                            (
                                int(math.log(operand.step, 2)) - 1
                            ) + operand.shift
                        ), field.size + int(math.log(operand.step, 2)) - 1 +
                        operand.shift, (
                            (
                                int(math.log(operand.step, 2)) - 1
                            ) + operand.shift
                        )
                    )
                    oper_size_pairs.append(pair)

            if operand.address_relative or operand.address_absolute or (
                not operand.address_relative and operand.min < 0
            ):
                LOG.debug("C2 codification")
                new_pairs = []
                for oper, size, shift in oper_size_pairs:
                    new_pairs.append((twocs_to_int(oper, size), size, shift))
                oper_size_pairs += new_pairs

            #
            # Handle special codifications
            # TODO: This should be moved to the architecture
            # back-ends
            #
            # MB field on POWERPC
            special_condition = False
            if field.name in ["MB6", "ME6"]:
                LOG.debug("Special condition field 1")
                special_condition = True
                pair = (
                    (
                        (field_value >> 1) & 0b11111
                    ) | (
                        (field_value & 0b1) << 5
                    ), field.size, operand.shift
                )
                oper_size_pairs.append(pair)

            if field.name in ["SH6_5"]:
                LOG.debug("Special condition field 2")
                special_condition = True
                pair = (field_value + 32, 6, operand.shift)
                oper_size_pairs.append(pair)

            if field.name in ["Dd0", "Dd2"]:
                special_condition = True
                pair = (0, field.size, operand.shift)
                oper_size_pairs.append(pair)

            if field.name in ['Dd1']:
                special_condition = True

                dd2_value = bin_instr & 0b1
                dd0_value = (bin_instr >> 6) & (0b1111111111)

                value = (field_value << 1)
                value = value | dd2_value
                value = value | (dd0_value << 6)
                value = twocs_to_int(value, 16)
                pair = (value, 16, operand.shift)
                oper_size_pairs.append(pair)

            if field.name in ["dc", "dm"]:
                special_condition = True
                pair = (0, field.size, operand.shift)
                oper_size_pairs.append(pair)

            if field.name in ['dx']:
                special_condition = True

                dc_value = (bin_instr >> 6) & 0b1
                dm_value = (bin_instr >> 2) & 0b1

                value = field_value
                value = value | (dm_value << 5)
                value = value | (dc_value << 6)
                # value = twocs_to_int(value, 16)
                pair = (value, 7, operand.shift)
                oper_size_pairs.append(pair)

            # Z Fixes
            if field.name in ["DH1", "DH2"]:
                LOG.debug("Special condition field 3")
                special_condition = True
                pair = (0, field.size, operand.shift)
                oper_size_pairs.append(pair)

            if field.name in ["DL1", "DL2"]:
                LOG.debug("Special condition field 4")
                special_condition = True

                next_field_value = (
                    bin_instr >> (
                        (
                            (instr_type.format.length * 8) -
                            (processed_bits + 8)
                        )
                    )
                ) & (
                    (0b1 << 8) - 1
                )

                pair = (
                    field_value | (next_field_value << field.size),
                    field.size + 8, operand.shift
                )
                oper_size_pairs.append(pair)
                pair = (twocs_to_int(pair[0], pair[1]), pair[1], pair[2])
                oper_size_pairs.append(pair)

            # RISC-V fixes

            # List of immediate fixes which need to be performed
            riscv_fixes = {
                'sb_imm7': ('sb_imm5', 13, True, '12|10:5;#13;4:1|11'),
                's_imm7': ('s_imm5', 12, True, '11:5;#13;4:0'),
                'uj_imm20': (None, 21, True, '20|10:1|11|19:12'),
                'cw_imm3': ('c_imm2', 7, False, '#3;5:3;#3;2|6'),
                'cd_imm3': ('c_imm2', 8, False, '#3;5:3;#3;7|6'),
                'cb_imm5': ('c_imm3', 9, True, '#3;8|4:3;#3;7:6|2:1|5'),
                'cw_imm5': ('c_imm1', 8, False, '#3;5;#5;4:2|7:6'),
                'cd_imm5': ('c_imm1', 9, False, '#3;5;#5;4:3|8:6'),
                'ci_imm5': ('c_imm1', 6, True, '#3;5;#5;4:0'),
                'cu_imm5': ('c_imm1', 20, False, '#3;5;#5;4:0', 5),
                'cs_imm5': ('c_imm1', 10, True, '#3;9;#5;4|6|8:7|5'),
                'cls_imm5': ('c_imm1', 6, False, '#3;5;#5;4:0'),
                'cw_imm6': (None, 8, False, '#3;5:2|7:6'),
                'cd_imm6': (None, 9, False, '#3;5:3|8:6'),
                'c_imm11': (None, 12, True, '#3;11|4|9:8|10|6|7|3:1|5'),
                'cs_imm8': (None, 10, False, '#3;5:4|9:6|2|3')
            }
            zero_fields = [fix[0] for _, (_, fix) in
                           enumerate(riscv_fixes.items())]

            def _parse_riscv_fix_field(fix):
                value = 0
                src_pos = (instr_type.format.length * 8) - 1

                segments = fix[3].split(';')
                for segment in segments:
                    if segment.startswith('#'):
                        src_pos -= int(segment[1:])
                    else:
                        tokens = segment.split('|')
                        for token in tokens:
                            if ':' in token:
                                start, end = map(int, token.split(':'))
                                for dst_pos in range(start, end - 1, -1):
                                    bit = (bin_instr >> src_pos) & 1
                                    value |= (bit << dst_pos)
                                    src_pos -= 1
                            else:
                                bit = (bin_instr >> src_pos) & 1
                                dst_pos = int(token)
                                value |= (bit << dst_pos)
                                src_pos -= 1

                if fix[2]:
                    value = twocs_to_int(value, fix[1])

                if len(fix) == 5 and (value >> fix[4]) > 0:
                    value = (1 << fix[1]) + twocs_to_int(value, fix[4]+1)

                return value

            # Fields which will contain the actual value
            if field.name in riscv_fixes:
                special_condition = True
                fix = riscv_fixes[field.name]
                value = _parse_riscv_fix_field(fix)
                pair = (value, fix[1], operand.shift)
                oper_size_pairs.append(pair)

            # Fields which will contain a 0
            if field.name in zero_fields:
                special_condition = True
                pair = (0, field.size, operand.shift)
                oper_size_pairs.append(pair)

            oper_size_pairs = list(set(oper_size_pairs))
            LOG.debug("Possible operand values: %s", oper_size_pairs)

            valid_values = []
            for operand_value, size, shift in oper_size_pairs:

                # Regular no shift
                valid = (
                    int(operand.codification(operand_value)) == field_value
                )

                # C2 no shift
                valid = valid or (
                    int_to_twocs(operand_value, size + shift) == field_value
                )

                # Regular shifted
                valid = valid or (
                    (
                        int(operand.codification(operand_value)) >> shift
                    ) == field_value
                )

                # C2 shifted
                valid = valid or (
                    (
                        int_to_twocs(operand_value, size + shift) >> shift
                    ) == field_value
                )

                # C2 shifted 2
                valid = valid or (
                    (
                        int_to_twocs(operand_value >> shift, size - shift)
                    ) == field_value
                )

                valid = valid or special_condition

                if valid:

                    LOG.debug("Codification matches")

                    try:

                        LOG.debug("Checking: %s", operand_value)
                        LOG.debug("Operand: %s", operand)
                        LOG.debug("Instruction type: %s", instr_type)
                        operand.check(operand_value)
                        valid_values.append(operand_value)
                        found = True
                        LOG.debug("Codification matches and valid value!")

                    except MicroprobeValueError as exc:
                        LOG.debug(exc)
                        LOG.debug("Codification matches but not valid value")

            operand_values.append(set(valid_values))

        else:

            LOG.debug("Non immediate operand")

            registers = []

            for value in operand.values():

                LOG.debug("Testing value: %s", value)
                if operand.codification(value) == "N/A":
                    continue

                int_val = int(operand.codification(value))
                valid = int_val == field_value

                if int_val > (2**field.size) - 1:

                    mask = (2**field.size) - 1
                    valid = valid or (int_val & mask) == field_value
                    valid = valid or ((int_val >> 1) & mask) == field_value

                # Handle POWERPC specific codification
                if (value.type.name).startswith("SPR"):
                    valid = (
                        ((int_val >> 5) & 0b11111) | (
                            (int_val & 0b11111) << 5
                        )
                    ) == field_value

                if field.name in ['TP']:
                    tmp_value = field_value << 0b1
                    tx_value = ((bin_instr >> 21) & 0b1) * 32
                    tmp_value = tx_value + tmp_value
                    if operand.codification(value) == str(tmp_value):
                        valid = True

                # Handle RISCV specific codification
                if field.name in ['crs1', 'crs2', 'crd',
                                  'fcrs1', 'fcrs2', 'fcrd']:
                    valid = (int_val & 0b1000
                             and (int_val & 0b111) == field_value)

                if valid:
                    try:
                        operand.check(value)
                        registers.append(value)
                        LOG.debug("Adding value: %s", value)
                    except MicroprobeValueError:
                        LOG.debug("Codification matches but not valid value")

            registers = list(set(registers))
            if len(registers) > 0:
                found = True
                operand_values.append(registers)

        if not found:
            return None

    LOG.debug("Operand values: %s", operand_values)
    return operand_values
Beispiel #3
0
    def binary(self, args, asm_args=None):

        LOG.debug("Start specific RISC-V codification")

        # Destination Field
        # Source Field
        # codification bits
        # Operand Descriptor
        # Codification
        # Signed?
        fixes = [
            ('sb_imm7', 'sb_imm7', 13, _7BITS_OPERAND_DESCRIPTOR, '12|10:5',
             True),
            ('sb_imm5', 'sb_imm7', 13, _7BITS_OPERAND_DESCRIPTOR, '4:1|11',
             True),
            ('s_imm7', 's_imm7', 12, _7BITS_OPERAND_DESCRIPTOR, '11:5', True),
            ('s_imm5', 's_imm7', 12, _7BITS_OPERAND_DESCRIPTOR, '4:0', True),
            ('uj_imm20', 'uj_imm20', 20, _20BITS_OPERAND_DESCRIPTOR,
             '20|10:1|11|19:12', True),
            ('cw_imm3', 'cw_imm3', 7, _7BITS_OPERAND_DESCRIPTOR, '5:3', False),
            ('c_imm2', 'cw_imm3', 7, _7BITS_OPERAND_DESCRIPTOR, '2|6', False),
            ('cd_imm3', 'cd_imm3', 8, _n_bits_operand_descriptor(8), '5:3',
             False),
            ('c_imm2', 'cd_imm3', 8, _n_bits_operand_descriptor(8), '7|6',
             False),
            ('cb_imm5', 'cb_imm5', 9, _n_bits_operand_descriptor(9),
             '7:6|2:1|5', True),
            ('c_imm3', 'cb_imm5', 9, _n_bits_operand_descriptor(9), '8|4:3',
             False),
            ('cw_imm5', 'cw_imm5', 8, _n_bits_operand_descriptor(8), '4:2|7:6',
             False),
            ('c_imm1', 'cw_imm5', 8, _n_bits_operand_descriptor(8), '5',
             False),
            ('cd_imm5', 'cd_imm5', 9, _n_bits_operand_descriptor(9), '4:3|8:6',
             False),
            ('c_imm1', 'cd_imm5', 9, _n_bits_operand_descriptor(9), '5',
             False),
            ('ci_imm5', 'ci_imm5', 6, _n_bits_operand_descriptor(6), '4:0',
             True),
            ('c_imm1', 'ci_imm5', 6, _n_bits_operand_descriptor(6), '5', True),
            ('cu_imm5', 'cu_imm5', 20, _n_bits_operand_descriptor(20), '4:0',
             False),
            ('c_imm1', 'cu_imm5', 20, _n_bits_operand_descriptor(20), '5',
             False),
            ('cs_imm5', 'cs_imm5', 10, _n_bits_operand_descriptor(10),
             '4|6|8:7|5', True),
            ('c_imm1', 'cs_imm5', 10, _n_bits_operand_descriptor(10), '9',
             False),
            ('cls_imm5', 'cls_imm5', 6, _n_bits_operand_descriptor(6), '4:0',
             False),
            ('c_imm1', 'cls_imm5', 6, _n_bits_operand_descriptor(6), '5',
             False),
            ('cw_imm6', 'cw_imm6', 8, _n_bits_operand_descriptor(8), '5:2|7:6',
             False),
            ('cd_imm6', 'cd_imm6', 9, _n_bits_operand_descriptor(9), '5:3|8:6',
             False),
            ('c_imm11', 'c_imm11', 12, _n_bits_operand_descriptor(12),
             '11|4|9:8|10|6|7|3:1|5', True),
            ('cs_imm8', 'cs_imm8', 10, _n_bits_operand_descriptor(10),
             '5:4|9:6|2|3', False),
            ('crs1', 'crs1', 5, _n_bits_operand_descriptor(3), '2:0', False),
            ('crs2', 'crs2', 5, _n_bits_operand_descriptor(3), '2:0', False),
            ('crd', 'crd', 5, _n_bits_operand_descriptor(3), '2:0', False),
            ('fcrs1', 'fcrs1', 5, _n_bits_operand_descriptor(3), '2:0', False),
            ('fcrs2', 'fcrs2', 5, _n_bits_operand_descriptor(3), '2:0', False),
            ('fcrd', 'fcrd', 5, _n_bits_operand_descriptor(3), '2:0', False),
        ]

        # Check if fixing is needed
        fix_needed = False
        for (name, _, _, _, _, _) in fixes:
            if name in [field.name for field in self.format.fields]:
                fix_needed = True
                break

        if not fix_needed:

            long_str = super(RISCVInstruction, self).binary(args,
                                                            asm_args=asm_args)

            assert len(long_str) in [32, 16], len(long_str)
            LOG.debug("End specific RISC-V codification")

            return long_str

        def _code_fixed_field(value, codification):
            coded_value = 0

            segments = codification.split(';')
            for segment in segments:
                tokens = segment.split('|')
                for token in tokens:
                    if ':' in token:
                        start, end = token.split(':')
                        for pos in range(int(start), int(end) - 1, -1):
                            bit = (value >> (pos)) & 1
                            coded_value = (coded_value << 1) | bit
                    else:
                        pos = int(token)
                        bit = (value >> (pos)) & 1
                        coded_value = (coded_value << 1) | bit

            return coded_value

        fields = dict(
            zip([field.name for field in self.format.fields],
                zip(self.format.fields, list(self.operands.items()))))
        argdict = dict(
            zip([
                field.name
                for field in self.format.fields if field.default_show
            ], args))
        fixed_args = dict()

        for fix in fixes:
            if fix[0] in fields and fix[1] in argdict:
                field, op_descriptor = fields[fix[0]]
                arg = argdict[fix[1]]
                value = int(arg.type.codification(arg.value))
                newarg = InstructionOperandValue(fix[3])

                if fix[5]:
                    value_coded = int_to_twocs(value, fix[2])
                    assert twocs_to_int(value_coded, fix[2]) == value
                    value = value_coded

                try:
                    value <<= arg.type.shift
                except AttributeError:  # Shifting not always will be available
                    pass

                newarg.set_value(_code_fixed_field(value, fix[4]))
                fixed_args[fix[0]] = newarg

        newargs = []

        for op_descriptor, field in zip(list(self.operands.items()),
                                        self.format.fields):

            _, op_descriptor = op_descriptor
            operand, _ = op_descriptor

            LOG.debug("Field: %s", field)
            LOG.debug("Operand: %s", operand)

            if field.name in fixed_args:
                newargs.append(fixed_args[field.name])
            else:
                if ((operand.constant and field.default_show)
                        or (not operand.constant)):
                    LOG.debug("Not fixing field: %s", field.name)
                    newargs.append(argdict[field.name])

        LOG.debug("Args: %s, %s", args, newargs)

        long_str = super(RISCVInstruction, self).binary(newargs, asm_args=args)
        assert len(long_str) in [16, 32], len(long_str)
        LOG.debug("End specific RISC-V codification")
        return long_str
Beispiel #4
0
def _interpret_bin_instr(instr_type, bin_instr):
    """

    :param target:
    :type target:
    """
    LOG.debug("Interpret bin instr: %s, %s", instr_type, hex(bin_instr))

    operand_values = []
    processed_bits = 0
    for op_descriptor, field in zip(
        list(instr_type.operands.items()), instr_type.format.fields
    ):
        dummy_fieldname, op_descriptor = op_descriptor
        operand, dummy_io_def = op_descriptor

        processed_bits += field.size

        LOG.debug("Process field: %s, size: %d", field, field.size)
        LOG.debug("Process operand: %s", operand)
        LOG.debug("Processed bits: %d", processed_bits)

        if not field.default_show:
            LOG.debug("Skip, not shown")
            continue

        field_value = (
            bin_instr >> (
                (
                    (instr_type.format.length * 8) - processed_bits
                )
            )
        ) & (
            (0b1 << field.size) - 1
        )

        LOG.debug("All: 0x%x", bin_instr)
        LOG.debug(
            "Shift bits: %d", (instr_type.format.length * 8) - processed_bits
        )
        LOG.debug(
            "Shifted value: 0x%x", (
                bin_instr >> (
                    (
                        (instr_type.format.length * 8) - processed_bits
                    )
                )
            )
        )
        LOG.debug("Field size: %d", field.size)
        LOG.debug("Mask used: 0x%x", (0b1 << field.size) - 1)
        LOG.debug("Field value: %s", hex(field_value))
        LOG.debug("Field value: %s", bin(field_value))

        found = False
        if (operand.immediate or
                operand.address_relative or operand.address_absolute):

            LOG.debug("Immediate/Relative operand")
            oper_size_pairs = [(field_value, field.size, 0)]

            if operand.shift > 0:

                LOG.debug("Operand shifted by: %s", operand.shift)
                pair = (
                    field_value << operand.shift, field.size + operand.shift,
                    operand.shift
                )
                oper_size_pairs.append(pair)

            if hasattr(operand, "step"):

                LOG.debug("Operand has a step of: %s", operand.step)
                for idx in [0, 1, 2]:

                    if (int(math.log(operand.step, 2)) - idx) < 0:
                        continue

                    pair = (
                        field_value << (
                            int(math.log(operand.step, 2)) - idx
                        ), field.size + int(math.log(operand.step, 2)) - idx,
                        (int(math.log(operand.step, 2)) - idx)
                    )
                    oper_size_pairs.append(pair)

                if operand.shift > 0:

                    LOG.debug(
                        "Operand shifted/stepped: %s %s", operand.shift,
                        operand.step
                    )
                    pair = (
                        field_value << (
                            (
                                int(math.log(operand.step, 2)) - 1
                            ) + operand.shift
                        ), field.size + int(math.log(operand.step, 2)) - 1 +
                        operand.shift, (
                            (
                                int(math.log(operand.step, 2)) - 1
                            ) + operand.shift
                        )
                    )
                    oper_size_pairs.append(pair)

            if operand.address_relative or operand.address_absolute or (
                not operand.address_relative and operand.min < 0
            ):
                LOG.debug("C2 codification")
                new_pairs = []
                for oper, size, shift in oper_size_pairs:
                    new_pairs.append((twocs_to_int(oper, size), size, shift))
                oper_size_pairs += new_pairs

            #
            # Handle special codifications
            #
            # MB field on POWERPC
            special_condition = False
            if field.name in ["MB6", "ME6"]:
                LOG.debug("Special condition field 1")
                special_condition = True
                pair = (
                    (
                        (field_value >> 1) & 0b11111
                    ) | (
                        (field_value & 0b1) << 5
                    ), field.size, operand.shift
                )
                oper_size_pairs.append(pair)

            if field.name in ["SH6_5"]:
                LOG.debug("Special condition field 2")
                special_condition = True
                pair = (field_value + 32, 6, operand.shift)
                oper_size_pairs.append(pair)

            if field.name in ["DH1", "DH2"]:
                LOG.debug("Special condition field 3")
                special_condition = True
                pair = (0, field.size, operand.shift)
                oper_size_pairs.append(pair)

            if field.name in ["DL1", "DL2"]:
                LOG.debug("Special condition field 4")
                special_condition = True

                next_field_value = (
                    bin_instr >> (
                        (
                            (instr_type.format.length * 8) -
                            (processed_bits + 8)
                        )
                    )
                ) & (
                    (0b1 << 8) - 1
                )

                pair = (
                    field_value | (next_field_value << field.size),
                    field.size + 8, operand.shift
                )
                oper_size_pairs.append(pair)
                pair = (twocs_to_int(pair[0], pair[1]), pair[1], pair[2])
                oper_size_pairs.append(pair)

            # RISC-V fixes
            if field.name in ["s_imm5", "sb_imm5"]:
                LOG.debug("Special condition field 5")
                special_condition = True
                pair = (0, field.size, operand.shift)
                oper_size_pairs.append(pair)

            if field.name in ["s_imm7", "sb_imm7"]:
                LOG.debug("Special condition field 6")
                special_condition = True

                field_value = ((field_value << 5) |
                               ((bin_instr >> 0x7) & ((0b1 << 5) - 1)))

                pair = (twocs_to_int(field_value, field.size + 5),
                        field.size + 5, operand.shift)
                oper_size_pairs.append(pair)

            oper_size_pairs = list(set(oper_size_pairs))
            LOG.debug("Possible operand values: %s", oper_size_pairs)

            valid_values = []
            for operand_value, size, shift in oper_size_pairs:

                # Regular no shift
                valid = (
                    int(operand.codification(operand_value)) == field_value
                )

                # C2 no shift
                valid = valid or (
                    int_to_twocs(operand_value, size) == field_value
                )

                # Regular shifted
                valid = valid or (
                    (
                        int(operand.codification(operand_value)) >> shift
                    ) == field_value
                )
                # C2 shifted
                valid = valid or (
                    (
                        int_to_twocs(operand_value, size) >> shift
                    ) == field_value
                )

                valid = valid or special_condition

                if valid:

                    LOG.debug("Codification matches")

                    try:

                        LOG.debug("Checking: %s", operand_value)
                        LOG.debug("Operand: %s", operand)
                        LOG.debug("Instruction type: %s", instr_type)
                        operand.check(operand_value)
                        valid_values.append(operand_value)
                        found = True
                        LOG.debug("Codification matches and valid value!")

                    except MicroprobeValueError as exc:
                        LOG.debug(exc)
                        LOG.debug("Codification matches but not valid value")

            operand_values.append(set(valid_values))

        else:

            LOG.debug("Non immediate operand")

            registers = []

            for value in operand.values():

                LOG.debug("Testing value: %s", value)
                int_val = int(operand.codification(value))
                valid = int_val == field_value

                if int_val > (2**field.size) - 1:

                    mask = (2**field.size) - 1
                    valid = valid or (int_val & mask) == field_value
                    valid = valid or ((int_val >> 1) & mask) == field_value

                # Handle POWERPC specific codification
                if (value.type.name) == "SPR":
                    valid = (
                        ((int_val >> 5) & 0b11111) | (
                            (int_val & 0b11111) << 5
                        )
                    ) == field_value

                if valid:
                    try:
                        operand.check(value)
                        registers.append(value)
                        LOG.debug("Adding value: %s", value)
                    except MicroprobeValueError:
                        LOG.debug("Codification matches but not valid value")

            registers = list(set(registers))
            if len(registers) > 0:
                found = True
                operand_values.append(registers)

        if not found:
            return None

    LOG.debug("Operand values: %s", operand_values)
    return operand_values
Beispiel #5
0
    def binary(self, args, asm_args=None):

        LOG.debug("Start specific RISC-V codification")

        # Check if fixing is needed
        fix_needed = False
        fix_fields = ['sb_imm5', 's_imm5']
        base_fields = ['sb_imm7', 's_imm7']

        for fix_field in fix_fields:
            if fix_field in [field.name for field in self.format.fields]:
                fix_needed = True
                break

        if not fix_needed:

            long_str = super(RISCVInstruction, self).binary(args,
                                                            asm_args=asm_args)

            assert len(long_str) in [32], len(long_str)
            LOG.debug("End specific RISC-V codification")

            return long_str

        next_operand_value = getnextf(iter(args))
        newargs = []

        for op_descriptor, field in zip(list(self.operands.items()),
                                        self.format.fields):

            dummy_fieldname, op_descriptor = op_descriptor
            operand, dummy = op_descriptor

            LOG.debug("Field: %s", field)
            LOG.debug("Operand: %s", operand)

            if (operand.constant
                    and (field.name not in fix_fields + base_fields)):

                if field.default_show:
                    arg = next_operand_value()
                    newargs.append(arg)

                continue

            if field.name not in fix_fields + base_fields:
                LOG.debug("Not fixing field: %s", field.name)
                arg = next_operand_value()
                newargs.append(arg)
                continue

            if field.name in base_fields:

                arg = next_operand_value()
                value = int(arg.type.codification(arg.value))
                value_coded = int_to_twocs(value, 12)

                assert twocs_to_int(value_coded, 12) == value

                newarg = InstructionOperandValue(_7BITS_OPERAND_DESCRIPTOR)
                newarg.set_value((value_coded & 0xFE0) >> 5)

                if field.name == "sb_imm7":
                    sb_imm5_value = (value_coded & 0x1F)
                elif field.name == "s_imm7":
                    s_imm5_value = (value_coded & 0x1F)
                else:
                    raise NotImplementedError

                LOG.debug("Set field '%s' value: %s --> %s", field.name, value,
                          (value_coded & 0xFE0) >> 5)
                newargs.append(newarg)

            # Assume variable are previously set
            if field.name in fix_fields:

                newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)

                if field.name == "sb_imm5":
                    value_fixed = sb_imm5_value
                elif field.name == "s_imm5":
                    value_fixed = s_imm5_value
                else:
                    raise NotImplementedError(field.name)

                LOG.debug("Set field '%s' value: %s --> %s", field.name, value,
                          value_fixed)

                newarg.set_value(value_fixed)
                newargs.append(newarg)

        LOG.debug("Args: %s, %s", args, newargs)

        long_str = super(RISCVInstruction, self).binary(newargs, asm_args=args)
        assert len(long_str) in [16, 32, 48], len(long_str)
        LOG.debug("End specific RISC-V codification")
        return long_str
Beispiel #6
0
    def set_register(self, register, value, context, opt=False):

        LOG.debug("Setting register: %s to value %d",
                  register.name, value)

        instrs = []

        current_value = context.get_register_value(register)
        closest_value = context.get_closest_value(value)

        if value == 0:
            present_reg = self.registers["X0"]

            if present_reg.type.name != register.type.name:
                present_reg = None

        elif context.register_has_value(value):
            present_reg = context.registers_get_value(value)[0]

            if present_reg.type.name != register.type.name:
                present_reg = None

        else:
            present_reg = None

        if register.type.name == "freg":

            LOG.debug("FP register")

            if present_reg is not None:

                LOG.debug("Value already present")

                instr = self.new_instruction("FSGNJ.S_V0")
                instr.set_operands([register, present_reg, present_reg])
                instrs.append(instr)

            else:

                LOG.debug("Setting value to scratch and "
                          "then move to FP register")

                instrs += self.set_register(self._scratch_registers[0], value,
                                            context)

                instr = self.new_instruction("FMV.D.X_V0")
                instr.set_operands([self._scratch_registers[0], register])
                instrs.append(instr)

        elif register.type.name == "ireg":

            LOG.debug("Integer register")

            if value == 0:

                LOG.debug("Zero value")

                addi = self.new_instruction("ADDI_V0")
                addi.set_operands([0, self.registers["X0"], register])
                instrs.append(addi)

            elif present_reg is not None:

                LOG.debug("Value already present")

                addi = self.new_instruction("ADDI_V0")
                addi.set_operands([0, present_reg, register])
                instrs.append(addi)

            elif (closest_value is not None and
                  abs(value - closest_value[1]) < (2 ** 12)):

                addi = self.new_instruction("ADDI_V0")
                addi.set_operands(
                    [value - closest_value[1], closest_value[0], register]
                )
                instrs.append(addi)

            else:

                if value <= 0:
                    value = int_to_twocs(value, 64)

                register = self._scratch_registers[0]

                value_highest = int((value & 0xFFFFF00000000000) >> 44)
                value_high = int((value & 0x00000FFF00000000) >> 32)
                value_low = int((value & 0x00000000FFFFF000) >> 12)
                value_lowest = int((value & 0x0000000000000FFF))

                if register == self._scratch_registers[0] and \
                   (value_highest != 0 or value_high != 0):

                    binstr = "{0:>064b}".format(value)
                    size = 11

                    sidx = binstr.find('1')
                    fidx = min(sidx+size, 64)

                    val = int(binstr[sidx:fidx], 2)
                    if val != 0:
                        addi = self.new_instruction("ADDI_V0")
                        addi.set_operands(
                            [val, self.registers["X0"], register]
                        )
                        instrs.append(addi)

                    sidx2 = binstr.find('1', fidx)
                    fidx2 = min(sidx2+size, 64)

                    tshift = fidx2

                    while fidx2-fidx > 0:
                        slli = self.new_instruction("SLLI_V0")
                        slli.set_operands([fidx2-fidx, register, register])
                        instrs.append(slli)

                        tshift = fidx2-fidx - tshift

                        val = int(binstr[sidx2:fidx2], 2)
                        if val != 0:
                            addi = self.new_instruction("ADDI_V0")
                            addi.set_operands([val, register, register])
                            instrs.append(addi)

                        sidx = sidx2
                        fidx = fidx2
                        sidx2 = binstr.find('1', fidx)
                        fidx2 = min(sidx2+size, 64)

                    if fidx < 64:
                        slli = self.new_instruction("SLLI_V0")
                        slli.set_operands([64-fidx, register, register])
                        instrs.append(slli)

                    LOG.debug(
                        "Register: %s set to value %d", register.name, value
                    )

                    return instrs

                if value_highest != 0:
                    lui = self.new_instruction("LUI_V0")
                    lui.set_operands([value_highest, register])
                    instrs.append(lui)

                if value_highest == 0 and value_high != 0:
                    if value_high > 2047:
                        addi = self.new_instruction("ADDI_V0")
                        addi.set_operands(
                            [2047, self.registers["X0"], register]
                        )
                        instrs.append(addi)
                        cvalue = value_high
                        while (cvalue > 2047):
                            addi = self.new_instruction("ADDI_V0")
                            addi.set_operands([2047, register, register])
                            instrs.append(addi)
                            cvalue = cvalue - 2047
                        addi = self.new_instruction("ADDI_V0")
                        addi.set_operands([cvalue, register, register])
                        instrs.append(addi)
                    else:
                        addi = self.new_instruction("ADDI_V0")
                        addi.set_operands(
                            [value_high, self.registers["X0"], register]
                        )
                        instrs.append(addi)

                elif value_highest != 0 and value_high != 0:
                    if value_high > 2047:
                        cvalue = value_high
                        while (cvalue > 2047):
                            addi = self.new_instruction("ADDI_V0")
                            addi.set_operands([2047, register, register])
                            instrs.append(addi)
                            cvalue = cvalue - 2047
                        addi = self.new_instruction("ADDI_V0")
                        addi.set_operands([cvalue, register, register])
                        instrs.append(addi)
                    else:
                        addi = self.new_instruction("ADDI_V0")
                        addi.set_operands([value_high, register, register])
                        instrs.append(addi)

                if value_highest != 0 or value_high != 0:
                    slli = self.new_instruction("SLLI_V0")
                    slli.set_operands([32, register, register])
                    instrs.append(slli)

                if value_highest == 0 or value_high == 0:

                    if value_low != 0:
                        lui = self.new_instruction("LUI_V0")
                        lui.set_operands([value_low, register])
                        instrs.append(lui)

                    if value_low == 0 and value_lowest != 0:
                        if value_lowest > 2047:
                            addi = self.new_instruction("ADDI_V0")
                            addi.set_operands(
                                [2047, self.registers["X0"], register]
                            )
                            instrs.append(addi)
                            cvalue = value_lowest
                            while (cvalue > 2047):
                                addi = self.new_instruction("ADDI_V0")
                                addi.set_operands([2047, register, register])
                                instrs.append(addi)
                                cvalue = cvalue - 2047
                            addi = self.new_instruction("ADDI_V0")
                            addi.set_operands([cvalue, register, register])
                            instrs.append(addi)
                        else:
                            addi = self.new_instruction("ADDI_V0")
                            addi.set_operands(
                                [value_lowest, self.registers["X0"], register]
                            )
                            instrs.append(addi)
                    elif value_low != 0 and value_lowest != 0:
                        if value_lowest > 2047:
                            cvalue = value_lowest
                            while (cvalue > 2047):
                                addi = self.new_instruction("ADDI_V0")
                                addi.set_operands([2047, register, register])
                                instrs.append(addi)
                                cvalue = cvalue - 2047
                            addi = self.new_instruction("ADDI_V0")
                            addi.set_operands([cvalue, register, register])
                            instrs.append(addi)
                        else:
                            addi = self.new_instruction("ADDI_V0")
                            addi.set_operands(
                                [value_lowest, register, register]
                            )
                            instrs.append(addi)
                else:
                    instrs.extend(
                        self.set_register(
                            self._scratch_registers[0],
                            (value & 0x00000000FFFFFFFF),
                            context
                        )
                    )
                    add_inst = self.new_instruction("ADD_V0")
                    add_inst.set_operands(
                        [register, self._scratch_registers[0], register])
                    instrs.append(add_inst)

                LOG.debug("Register: %s set to value %d",
                          register.name, value)

        else:
            LOG.debug("Register: %s set to value %d",
                      register.name, value)
            raise NotImplementedError

        if len(instrs) > 0:
            return instrs

        return super(RISCVISA, self).set_register(register, value, context)
Beispiel #7
0
    def binary(self, args, dummy_asm_args=None):

        LOG.debug("Start specific PowerPC codification")

        # Check if fixing is needed
        fix_needed = False
        fix_fields = [
            'SH0', 'CX', 'AX', 'BX', 'TX', 'SX', 'MB6', 'ME6', 'SPR', 'D_14dw',
            'D_14sw', 'D_14qw2', 'Dd0', 'Dd2', 'dc', 'dm'
        ]
        base_fields = [
            'SH6_5', 'C', 'A', 'Ap', 'B', 'S', 'T', 'TP', 'Dd1', 'dx'
        ]

        for fix_field in fix_fields:
            if fix_field in [field.name for field in self.format.fields]:
                fix_needed = True
                break

        if not fix_needed:
            long_str = super(PowerInstruction, self).binary(args)

            assert len(long_str) == 32, \
                "Bad PowerPC codification. Length: %d " % len(
                long_str)

            LOG.debug("End specific PowerPC codification")
            return long_str

        next_operand_value = getnextf(iter(args))
        newargs = []

        for op_descriptor, field in zip(list(self.operands.items()),
                                        self.format.fields):

            dummy_fieldname, op_descriptor = op_descriptor
            operand, dummy = op_descriptor

            LOG.debug("Field: %s", field)
            LOG.debug("Operand: %s", operand)

            if (operand.constant
                    and (field.name not in fix_fields + base_fields)):

                if field.default_show:
                    arg = next_operand_value()
                    newargs.append(arg)

                continue

            if field.name not in fix_fields + base_fields:
                LOG.debug("Not fixing field: %s", field.name)
                arg = next_operand_value()
                newargs.append(arg)
                continue

            if field.name in base_fields:

                arg = next_operand_value()
                value = int(arg.type.codification(arg.value))

                if field.name == 'SH6_5':
                    sh0_value = (value & 0x20) >> 5
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value(value & 0x1F)
                elif field.name == "A":
                    ax_value = (value & 0x20) >> 5
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value(value & 0x1F)
                elif field.name == "Ap":
                    ax_value = (value & 0x20) >> 5
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value(value & 0x1F)
                elif field.name == "B":
                    bx_value = (value & 0x20) >> 5
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value(value & 0x1F)
                elif field.name == "C":
                    cx_value = (value & 0x20) >> 5
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value(value & 0x1F)
                elif field.name == "T":
                    tx_value = (value & 0x20) >> 5
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value(value & 0x1F)
                elif field.name in "TP":
                    tx_value = (value & 0b100000) >> 5
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value((value & 0b011111) >> 1)
                elif field.name == "S":
                    sx_value = (value & 0x20) >> 5
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value(value & 0x1F)
                elif field.name == "dx":
                    dm_value = (value >> 5) & 0b1
                    dc_value = (value >> 6) & 0b1
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value(value & 0x1F)
                elif field.name == "Dd1":
                    value = int_to_twocs(value, 16)
                    dd0_value = value >> 6
                    dd2_value = value & 0b1
                    newarg = InstructionOperandValue(_5BITS_OPERAND_DESCRIPTOR)
                    newarg.set_value((value >> 1) & 0b11111)
                else:
                    raise NotImplementedError

                newargs.append(newarg)
                LOG.debug("Set field value: %s --> %s", value, newarg.value)

            # Assume variable are previously set
            if field.name in fix_fields:

                newarg = InstructionOperandValue(_1BIT_OPERAND_DESCRIPTOR)

                if field.name == 'SH0':
                    value = sh0_value
                elif field.name == "AX":
                    value = ax_value
                elif field.name == "BX":
                    value = bx_value
                elif field.name == "CX":
                    value = cx_value
                elif field.name == "TX":
                    value = tx_value
                elif field.name == "SX":
                    value = sx_value
                elif field.name == "dm":
                    value = dm_value
                elif field.name == "dc":
                    value = dc_value
                elif field.name in ["MB6", "ME6"]:
                    arg = next_operand_value()
                    newarg = arg.copy()
                    value = int(arg.type.codification(arg.value))
                    value = ((value & 0x1F) << 1) | ((value & 0x20) >> 5)
                elif field.name in ["SPR"]:
                    arg = next_operand_value()
                    newarg = InstructionOperandValue(
                        _10BITS_OPERAND_DESCRIPTOR)
                    value = int(arg.type.codification(arg.value))
                    value = ((value & 0x1F) << 5) | ((value & 0x3E0) >> 5)
                elif field.name in [
                        'D_14dw',
                        'D_14sw',
                        'D_14qw2',
                ]:
                    arg = next_operand_value()
                    # newarg = arg.copy()
                    newarg = InstructionOperandValue(
                        _14BITS_OPERAND_DESCRIPTOR)
                    value = int(arg.type.codification(arg.value))
                    value = value >> 2
                elif field.name == "Dd0":
                    newarg = arg.copy()
                    value = dd0_value
                elif field.name == "Dd2":
                    newarg = arg.copy()
                    value = dd2_value
                else:
                    raise NotImplementedError

                LOG.debug("Set field to value: %s", value)
                newarg.set_value(value)
                newargs.append(newarg)

        LOG.debug("New args: %s", newargs)

        long_str = super(PowerInstruction, self).binary(newargs, asm_args=args)

        assert len(long_str) == 32, "Bad PowerPC codification. Length: %d " \
            % len(long_str)

        LOG.debug("End specific PowerPC codification")

        return long_str