예제 #1
0
파일: bin.py 프로젝트: IBM/microprobe
            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
예제 #2
0
def _shift_and_fix_registers(registers, offset, addresses, min_address):
    """Shift register contents."""
    sregisters = []
    for register in registers:
        register = register.copy()
        if not register.name.startswith("GPR"):
            # Do not shift not GPR registers
            sregisters.append(register)
            continue

        # if GPR value is a negative one, do not shift it
        value = twocs_to_int(register.value, 64)
        if value < 0:
            sregisters.append(register)
            continue

        if not ((addresses[0] <= register.value < addresses[1]) and
                register.value > min_address):
            sregisters.append(register)
            continue

        distance = min((abs(register.value - addr) for addr in addresses[2]))
        if distance > _FIX_ADDRESS_TOLERANCE:
            sregisters.append(register)
            continue

        print_info(
            "Shift '%s' from '0x%016X' to '0x%016X'" %
            (register.name,
             register.value,
             register.value + offset),
        )
        register.value = register.value + offset

        fmt_str = "{0:064b}"
        value_coded = fmt_str.format(register.value)
        if len(value_coded) > 64:
            print_warning(
                "Overflow during shifting. Cropping of"
                " register '%s'" % register.name
            )
            register.value = int(value_coded[-64:], 2)
        sregisters.append(register)

    return sregisters
예제 #3
0
파일: bin.py 프로젝트: IBM/microprobe
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
예제 #4
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
예제 #5
0
파일: asm.py 프로젝트: karthiksv/microprobe
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)
예제 #6
0
파일: bin.py 프로젝트: karthiksv/microprobe
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
예제 #7
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