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