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
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
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
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
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)
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
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