def process_memory_address(self, memory_address): """Post-process memory address operand""" # Remove unecessarily created dictionary entries during memory address parsing offset = memory_address.get("offset", None) base = memory_address.get("base", None) index = memory_address.get("index", None) scale = 1 if "scale" not in memory_address else int( memory_address["scale"], 0) if isinstance(offset, str) and base is None and index is None: try: offset = {"value": int(offset, 0)} except ValueError: offset = {"value": offset} elif offset is not None and "value" in offset: offset["value"] = int(offset["value"], 0) new_dict = AttrDict({ "offset": offset, "base": base, "index": index, "scale": scale }) # Add segmentation extension if existing if self.SEGMENT_EXT_ID in memory_address: new_dict[self.SEGMENT_EXT_ID] = memory_address[self.SEGMENT_EXT_ID] return AttrDict({self.MEMORY_ID: new_dict})
def process_immediate(self, immediate): """Post-process immediate operand""" dict_name = '' if 'identifier' in immediate: # actually an identifier, change declaration return immediate if 'value' in immediate: # normal integer value, nothing to do return AttrDict({self.IMMEDIATE_ID: immediate}) if 'base_immediate' in immediate: # arithmetic immediate, add calculated value as value immediate['shift'] = immediate['shift'][0] immediate['value'] = int( immediate['base_immediate']['value']) << int( immediate['shift']['value']) return AttrDict({self.IMMEDIATE_ID: immediate}) if 'float' in immediate: dict_name = 'float' if 'double' in immediate: dict_name = 'double' if 'exponent' in immediate[dict_name]: # nothing to do return AttrDict({self.IMMEDIATE_ID: immediate}) else: # change 'mantissa' key to 'value' return AttrDict({ self.IMMEDIATE_ID: AttrDict({'value': immediate[dict_name]['mantissa']}) })
def resolve_range_list(self, operand): """ Resolve range or list register operand to list of registers. Returns None if neither list nor range """ if 'register' in operand: if 'list' in operand.register: index = operand.register.get('index') range_list = [] for reg in operand.register.list: reg = deepcopy(reg) if index is not None: reg['index'] = int(index, 0) range_list.append(AttrDict({self.REGISTER_ID: reg})) return range_list elif 'range' in operand.register: base_register = operand.register.range[0] index = operand.register.get('index') range_list = [] start_name = base_register.name end_name = operand.register.range[1].name for name in range(int(start_name), int(end_name) + 1): reg = deepcopy(base_register) if index is not None: reg['index'] = int(index, 0) reg['name'] = str(name) range_list.append(AttrDict({self.REGISTER_ID: reg})) return range_list # neither register list nor range, return unmodified return operand
def process_immediate(self, immediate): """Post-process immediate operand""" dict_name = "" if "identifier" in immediate: # actually an identifier, change declaration return immediate if "value" in immediate: # normal integer value immediate["type"] = "int" # convert hex/bin immediates to dec immediate["value"] = self.normalize_imd(immediate) return AttrDict({self.IMMEDIATE_ID: immediate}) if "base_immediate" in immediate: # arithmetic immediate, add calculated value as value immediate["shift"] = immediate["shift"][0] immediate["value"] = self.normalize_imd(immediate["base_immediate"]) << int( immediate["shift"]["value"] ) immediate["type"] = "int" return AttrDict({self.IMMEDIATE_ID: immediate}) if "float" in immediate: dict_name = "float" if "double" in immediate: dict_name = "double" if "exponent" in immediate[dict_name]: immediate["type"] = dict_name return AttrDict({self.IMMEDIATE_ID: immediate}) else: # change 'mantissa' key to 'value' return AttrDict({ self.IMMEDIATE_ID: AttrDict({ "value": immediate[dict_name]["mantissa"], "type": dict_name})} )
def process_memory_address(self, memory_address): """Post-process memory address operand""" # Remove unnecessarily created dictionary entries during parsing offset = memory_address.get("offset", None) if isinstance(offset, list) and len(offset) == 1: offset = offset[0] if offset is not None and "value" in offset: offset["value"] = int(offset["value"], 0) base = memory_address.get("base", None) index = memory_address.get("index", None) scale = 1 if base is not None and "name" in base and base["name"] == "sp": base["prefix"] = "x" if index is not None and "name" in index and index["name"] == "sp": index["prefix"] = "x" valid_shift_ops = ["lsl", "uxtw", "sxtw"] if "index" in memory_address: if "shift" in memory_address["index"]: if memory_address["index"]["shift_op"].lower() in valid_shift_ops: scale = 2 ** int(memory_address["index"]["shift"][0]["value"]) new_dict = AttrDict({"offset": offset, "base": base, "index": index, "scale": scale}) if "pre_indexed" in memory_address: new_dict["pre_indexed"] = True if "post_indexed" in memory_address: if "value" in memory_address["post_indexed"]: new_dict["post_indexed"] = {"value": int( memory_address["post_indexed"]["value"], 0 )} else: new_dict["post_indexed"] = memory_address["post_indexed"] return AttrDict({self.MEMORY_ID: new_dict})
def parse_instruction(self, instruction): """ Parse instruction in asm line. :param str instruction: Assembly line string. :returns: `dict` -- parsed instruction form """ result = self.instruction_parser.parseString(instruction, parseAll=True).asDict() result = AttrDict.convert_dict(result) operands = [] # Add operands to list # Check first operand if 'operand1' in result: operands.append(self.process_operand(result['operand1'])) # Check second operand if 'operand2' in result: operands.append(self.process_operand(result['operand2'])) # Check third operand if 'operand3' in result: operands.append(self.process_operand(result['operand3'])) # Check fourth operand if 'operand4' in result: operands.append(self.process_operand(result['operand4'])) return_dict = AttrDict({ self.INSTRUCTION_ID: result['mnemonic'], self.OPERANDS_ID: operands, self.COMMENT_ID: ' '.join(result[self.COMMENT_ID]) if self.COMMENT_ID in result else None, }) return return_dict
def process_memory_address(self, memory_address): """Post-process memory address operand""" # Remove unnecessarily created dictionary entries during parsing offset = memory_address.get('offset', None) if isinstance(offset, list) and len(offset) == 1: offset = offset[0] base = memory_address.get('base', None) index = memory_address.get('index', None) scale = 1 if base is not None and 'name' in base and base['name'] == 'sp': base['prefix'] = 'x' if index is not None and 'name' in index and index['name'] == 'sp': index['prefix'] = 'x' valid_shift_ops = ['lsl', 'uxtw', 'sxtw'] if 'index' in memory_address: if 'shift' in memory_address['index']: if memory_address['index']['shift_op'].lower( ) in valid_shift_ops: scale = 2**int(memory_address['index']['shift']['value']) new_dict = AttrDict({ 'offset': offset, 'base': base, 'index': index, 'scale': scale }) if 'pre_indexed' in memory_address: new_dict['pre_indexed'] = True if 'post_indexed' in memory_address: new_dict['post_indexed'] = memory_address['post_indexed'] return AttrDict({self.MEMORY_ID: new_dict})
def _apply_found_ISA_data(self, isa_data, operands): """ Create operand dictionary containing src/dst operands out of the ISA data entry and the oeprands of an instruction form If breaks_pedendency_on_equal_operands is True (configuted per instruction in ISA db) and all operands are equal, place operand into destination only. :param dict isa_data: ISA DB entry :param list operands: operands of the instruction form :returns: `dict` -- operands dictionary with src/dst assignment """ op_dict = {} op_dict["source"] = [] op_dict["destination"] = [] op_dict["src_dst"] = [] # handle dependency breaking instructions if "breaks_pedendency_on_equal_operands" in isa_data and operands[ 1:] == operands[:-1]: op_dict["destination"] += operands if "hidden_operands" in isa_data: op_dict["destination"] += [ AttrDict.convert_dict({ hop["class"]: { k: hop[k] for k in ["class", "source", "destination"] } }) for hop in isa_data["hidden_operands"] ] return op_dict for i, op in enumerate(isa_data["operands"]): if op["source"] and op["destination"]: op_dict["src_dst"].append(operands[i]) continue if op["source"]: op_dict["source"].append(operands[i]) continue if op["destination"]: op_dict["destination"].append(operands[i]) continue # check for hidden operands like flags or registers if "hidden_operands" in isa_data: # add operand(s) to semantic_operands of instruction form for op in isa_data["hidden_operands"]: dict_key = ("src_dst" if op["source"] and op["destination"] else "source" if op["source"] else "destination") hidden_op = {op["class"]: {}} key_filter = ["class", "source", "destination"] for key in [k for k in op.keys() if k not in key_filter]: hidden_op[op["class"]][key] = op[key] hidden_op = AttrDict.convert_dict(hidden_op) op_dict[dict_key].append(hidden_op) return op_dict
def test_multiple_regs(self): instr_range = "PUSH {x5-x7}" instr_list = "POP {x5, x6, x7}" instr_range_with_index = "ld4 {v0.S - v3.S}[2]" instr_list_with_index = "ld4 {v0.S, v1.S, v2.S, v3.S}[2]" instr_range_single = "dummy { z1.d }" reg_list = [ AttrDict({"register": {"prefix": "x", "name": "5"}}), AttrDict({"register": {"prefix": "x", "name": "6"}}), AttrDict({"register": {"prefix": "x", "name": "7"}}), ] reg_list_idx = [ AttrDict({"register": {"prefix": "v", "name": "0", "shape": "S", "index": 2}}), AttrDict({"register": {"prefix": "v", "name": "1", "shape": "S", "index": 2}}), AttrDict({"register": {"prefix": "v", "name": "2", "shape": "S", "index": 2}}), AttrDict({"register": {"prefix": "v", "name": "3", "shape": "S", "index": 2}}), ] reg_list_single = [AttrDict({"register": {"prefix": "z", "name": "1", "shape": "d"}})] prange = self.parser.parse_line(instr_range) plist = self.parser.parse_line(instr_list) p_idx_range = self.parser.parse_line(instr_range_with_index) p_idx_list = self.parser.parse_line(instr_list_with_index) p_single = self.parser.parse_line(instr_range_single) self.assertEqual(prange.operands, reg_list) self.assertEqual(plist.operands, reg_list) self.assertEqual(p_idx_range.operands, reg_list_idx) self.assertEqual(p_idx_list.operands, reg_list_idx) self.assertEqual(p_single.operands, reg_list_single)
def process_memory_address(self, memory_address): """Post-process memory address operand""" # Remove unecessarily created dictionary entries during memory address parsing offset = memory_address.get('offset', None) base = memory_address.get('base', None) index = memory_address.get('index', None) scale = 1 if 'scale' not in memory_address else int(memory_address['scale']) if isinstance(offset, str) and base is None and index is None: offset = {'value': offset} new_dict = AttrDict({'offset': offset, 'base': base, 'index': index, 'scale': scale}) # Add segmentation extension if existing if self.SEGMENT_EXT_ID in memory_address: new_dict[self.SEGMENT_EXT_ID] = memory_address[self.SEGMENT_EXT_ID] return AttrDict({self.MEMORY_ID: new_dict})
def test_register_funcs(self): reg_a1 = AttrDict({"name": "rax"}) reg_a2 = AttrDict({"name": "eax"}) register_string = "v1.2d" with self.assertRaises(NotImplementedError): self.parser.is_reg_dependend_of(reg_a1, reg_a2) with self.assertRaises(NotImplementedError): self.parser.parse_register(register_string) with self.assertRaises(NotImplementedError): self.parser.is_gpr(reg_a1) with self.assertRaises(NotImplementedError): self.parser.is_vector_register(reg_a1) with self.assertRaises(NotImplementedError): self.parser.process_operand(reg_a1) with self.assertRaises(NotImplementedError): self.parser.get_full_reg_name(reg_a1)
def process_directive(self, directive): directive_new = {"name": directive["name"], "parameters": []} if "parameters" in directive: directive_new["parameters"] = directive["parameters"] if "comment" in directive: directive_new["comment"] = directive["comment"] return AttrDict({self.DIRECTIVE_ID: directive_new})
def process_immediate(self, immediate): """Post-process immediate operand""" if 'identifier' in immediate: # actually an identifier, change declaration return immediate # otherwise nothing to do return AttrDict({self.IMMEDIATE_ID: immediate})
def process_directive(self, directive): directive_new = {'name': directive['name'], 'parameters': []} if 'parameters' in directive: directive_new['parameters'] = directive['parameters'] if 'comment' in directive: directive_new['comment'] = directive['comment'] return AttrDict({self.DIRECTIVE_ID: directive_new})
def process_immediate(self, immediate): """Post-process immediate operand""" if "identifier" in immediate: # actually an identifier, change declaration return immediate # otherwise just make sure the immediate is a decimal immediate["value"] = int(immediate["value"], 0) return AttrDict({self.IMMEDIATE_ID: immediate})
def process_register_list(self, register_list): """Post-process register lists (e.g., {r0,r3,r5}) and register ranges (e.g., {r0-r7})""" # Remove unnecessarily created dictionary entries during parsing rlist = [] dict_name = '' if 'list' in register_list: dict_name = 'list' if 'range' in register_list: dict_name = 'range' for r in register_list[dict_name]: rlist.append( AttrDict.convert_dict( self.list_element.parseString(r, parseAll=True).asDict())) index = register_list.get('index', None) new_dict = AttrDict({dict_name: rlist, 'index': index}) if len(new_dict[dict_name]) == 1: return AttrDict({self.REGISTER_ID: new_dict[dict_name][0]}) return AttrDict({self.REGISTER_ID: new_dict})
def parse_instruction(self, instruction): """ Parse instruction in asm line. :param str instruction: Assembly line string. :returns: `dict` -- parsed instruction form """ result = self.instruction_parser.parseString(instruction, parseAll=True).asDict() result = AttrDict.convert_dict(result) operands = [] # Add operands to list # Check first operand if "operand1" in result: operand = self.process_operand(result["operand1"]) operands.extend(operand) if isinstance(operand, list) else operands.append(operand) # Check second operand if "operand2" in result: operand = self.process_operand(result["operand2"]) operands.extend(operand) if isinstance(operand, list) else operands.append(operand) # Check third operand if "operand3" in result: operand = self.process_operand(result["operand3"]) operands.extend(operand) if isinstance(operand, list) else operands.append(operand) # Check fourth operand if "operand4" in result: operand = self.process_operand(result["operand4"]) operands.extend(operand) if isinstance(operand, list) else operands.append(operand) # Check fifth operand if "operand5" in result: operand = self.process_operand(result["operand5"]) operands.extend(operand) if isinstance(operand, list) else operands.append(operand) return_dict = AttrDict( { self.INSTRUCTION_ID: result.mnemonic, self.OPERANDS_ID: operands, self.COMMENT_ID: " ".join(result[self.COMMENT_ID]) if self.COMMENT_ID in result else None, } ) return return_dict
def test_multiple_regs(self): instr_range = 'PUSH {x5-x7}' reg_range = AttrDict({ 'register': { 'range': [{ 'prefix': 'x', 'name': '5' }, { 'prefix': 'x', 'name': '7' }], 'index': None } }) instr_list = 'POP {x5, x7, x9}' reg_list = AttrDict({ 'register': { 'list': [{ 'prefix': 'x', 'name': '5' }, { 'prefix': 'x', 'name': '7' }, { 'prefix': 'x', 'name': '9' }], 'index': None } }) prange = self.parser.parse_line(instr_range) plist = self.parser.parse_line(instr_list) self.assertEqual(prange.operands[0], reg_range) self.assertEqual(plist.operands[0], reg_list)
def test_is_read_is_written_x86(self): # independent form HW model dag = KernelDG(self.kernel_x86, self.parser_x86, None) reg_rcx = AttrDict({'name': 'rcx'}) reg_ymm1 = AttrDict({'name': 'ymm1'}) instr_form_r_c = self.parser_x86.parse_line( 'vmovsd %xmm0, (%r15,%rcx,8)') self.semantics_csx.assign_src_dst(instr_form_r_c) instr_form_non_r_c = self.parser_x86.parse_line( 'movl %xmm0, (%r15,%rax,8)') self.semantics_csx.assign_src_dst(instr_form_non_r_c) instr_form_w_c = self.parser_x86.parse_line('movi $0x05ACA, %rcx') self.semantics_csx.assign_src_dst(instr_form_w_c) instr_form_rw_ymm_1 = self.parser_x86.parse_line( 'vinsertf128 $0x1, %xmm1, %ymm0, %ymm1') self.semantics_csx.assign_src_dst(instr_form_rw_ymm_1) instr_form_rw_ymm_2 = self.parser_x86.parse_line( 'vinsertf128 $0x1, %xmm0, %ymm1, %ymm1') self.semantics_csx.assign_src_dst(instr_form_rw_ymm_2) instr_form_r_ymm = self.parser_x86.parse_line('vmovapd %ymm1, %ymm0') self.semantics_csx.assign_src_dst(instr_form_r_ymm) self.assertTrue(dag.is_read(reg_rcx, instr_form_r_c)) self.assertFalse(dag.is_read(reg_rcx, instr_form_non_r_c)) self.assertFalse(dag.is_read(reg_rcx, instr_form_w_c)) self.assertTrue(dag.is_written(reg_rcx, instr_form_w_c)) self.assertFalse(dag.is_written(reg_rcx, instr_form_r_c)) self.assertTrue(dag.is_read(reg_ymm1, instr_form_rw_ymm_1)) self.assertTrue(dag.is_read(reg_ymm1, instr_form_rw_ymm_2)) self.assertTrue(dag.is_read(reg_ymm1, instr_form_r_ymm)) self.assertTrue(dag.is_written(reg_ymm1, instr_form_rw_ymm_1)) self.assertTrue(dag.is_written(reg_ymm1, instr_form_rw_ymm_2)) self.assertFalse(dag.is_written(reg_ymm1, instr_form_r_ymm))
def _apply_found_ISA_data(self, isa_data, operands): """ Create operand dictionary containing src/dst operands out of the ISA data entry and the oeprands of an instruction form :param dict isa_data: ISA DB entry :param list operands: operands of the instruction form :returns: `dict` -- operands dictionary with src/dst assignment """ op_dict = {} op_dict['source'] = [] op_dict['destination'] = [] op_dict['src_dst'] = [] for i, op in enumerate(isa_data['operands']): if op['source'] and op['destination']: op_dict['src_dst'].append(operands[i]) continue if op['source']: op_dict['source'].append(operands[i]) continue if op['destination']: op_dict['destination'].append(operands[i]) continue # check for hidden operands like flags or registers if 'hidden_operands' in isa_data: # add operand(s) to semantic_operands of instruction form for op in isa_data['hidden_operands']: dict_key = ( 'src_dst' if op['source'] and op['destination'] else 'source' if op['source'] else 'destination' ) hidden_op = {op['class']: {}} key_filter = ['class', 'source', 'destination'] for key in [k for k in op.keys() if k not in key_filter]: hidden_op[op['class']][key] = op[key] hidden_op = AttrDict.convert_dict(hidden_op) op_dict[dict_key].append(hidden_op) return op_dict
def _get_comment(self, parser, comment): return ' '.join( AttrDict.convert_dict( parser.process_operand( parser.comment.parseString( comment, parseAll=True).asDict())).comment)
def process_label(self, label): """Post-process label asm line""" # remove duplicated 'name' level due to identifier label['name'] = label['name'][0]['name'] return AttrDict({self.LABEL_ID: label})
def parse_line(self, line, line_number=None): """ Parse line and return instruction form. :param str line: line of assembly code :param line_number: default None, identifier of instruction form :type line_number: int, optional :return: ``dict`` -- parsed asm line (comment, label, directive or instruction form) """ instruction_form = AttrDict({ self.INSTRUCTION_ID: None, self.OPERANDS_ID: [], self.DIRECTIVE_ID: None, self.COMMENT_ID: None, self.LABEL_ID: None, 'line': line, 'line_number': line_number, }) result = None # 1. Parse comment try: result = self.process_operand( self.comment.parseString(line, parseAll=True).asDict()) result = AttrDict.convert_dict(result) instruction_form[self.COMMENT_ID] = ' '.join( result[self.COMMENT_ID]) except pp.ParseException: pass # 2. Parse label if result is None: try: result = self.process_operand( self.label.parseString(line, parseAll=True).asDict()) result = AttrDict.convert_dict(result) instruction_form[self.LABEL_ID] = result[self.LABEL_ID]['name'] if self.COMMENT_ID in result[self.LABEL_ID]: instruction_form[self.COMMENT_ID] = ' '.join( result[self.LABEL_ID][self.COMMENT_ID]) except pp.ParseException: pass # 3. Parse directive if result is None: try: result = self.process_operand( self.directive.parseString(line, parseAll=True).asDict()) result = AttrDict.convert_dict(result) instruction_form[self.DIRECTIVE_ID] = AttrDict({ 'name': result[self.DIRECTIVE_ID]['name'], 'parameters': result[self.DIRECTIVE_ID]['parameters'], }) if self.COMMENT_ID in result[self.DIRECTIVE_ID]: instruction_form[self.COMMENT_ID] = ' '.join( result[self.DIRECTIVE_ID][self.COMMENT_ID]) except pp.ParseException: pass # 4. Parse instruction if result is None: try: result = self.parse_instruction(line) except pp.ParseException: raise ValueError( 'Could not parse instruction on line {}: {!r}'.format( line_number, line)) instruction_form[self.INSTRUCTION_ID] = result[self.INSTRUCTION_ID] instruction_form[self.OPERANDS_ID] = result[self.OPERANDS_ID] instruction_form[self.COMMENT_ID] = result[self.COMMENT_ID] return instruction_form
def process_identifier(self, identifier): """Post-process identifier operand""" # remove value if it consists of symbol+offset if 'value' in identifier: del identifier['value'] return AttrDict({self.IDENTIFIER_ID: identifier})
def process_sp_register(self, register): """Post-process stack pointer register""" reg = register reg['prefix'] = 'x' return AttrDict({self.REGISTER_ID: reg})
def parse_line(self, line, line_number=None): """ Parse line and return instruction form. :param str line: line of assembly code :param line_number: identifier of instruction form, defautls to None :type line_number: int, optional :return: `dict` -- parsed asm line (comment, label, directive or instruction form) """ instruction_form = AttrDict({ self.INSTRUCTION_ID: None, self.OPERANDS_ID: [], self.DIRECTIVE_ID: None, self.COMMENT_ID: None, self.LABEL_ID: None, 'line': line, 'line_number': line_number, }) result = None # 1. Parse comment try: result = self.process_operand( self.comment.parseString(line, parseAll=True).asDict()) result = AttrDict.convert_dict(result) instruction_form[self.COMMENT_ID] = ' '.join( result[self.COMMENT_ID]) except pp.ParseException: pass # 1.2 check for llvm-mca marker try: result = self.process_operand( self.llvm_markers.parseString(line, parseAll=True).asDict()) result = AttrDict.convert_dict(result) instruction_form[self.COMMENT_ID] = ' '.join( result[self.COMMENT_ID]) except pp.ParseException: pass # 2. Parse label if result is None: try: result = self.process_operand( self.label.parseString(line, parseAll=True).asDict()) result = AttrDict.convert_dict(result) instruction_form[self.LABEL_ID] = result[self.LABEL_ID].name if self.COMMENT_ID in result[self.LABEL_ID]: instruction_form[self.COMMENT_ID] = ' '.join( result[self.LABEL_ID][self.COMMENT_ID]) except pp.ParseException: pass # 3. Parse directive if result is None: try: result = self.process_operand( self.directive.parseString(line, parseAll=True).asDict()) result = AttrDict.convert_dict(result) instruction_form[self.DIRECTIVE_ID] = AttrDict({ 'name': result[self.DIRECTIVE_ID].name, 'parameters': result[self.DIRECTIVE_ID].parameters, }) if self.COMMENT_ID in result[self.DIRECTIVE_ID]: instruction_form[self.COMMENT_ID] = ' '.join( result[self.DIRECTIVE_ID][self.COMMENT_ID]) except pp.ParseException: pass # 4. Parse instruction if result is None: try: result = self.parse_instruction(line) except (pp.ParseException, KeyError): print( '\n\n*-*-*-*-*-*-*-*-*-*-\n{}: {}\n*-*-*-*-*-*-*-*-*-*-\n\n' .format(line_number, line)) instruction_form[self.INSTRUCTION_ID] = result[self.INSTRUCTION_ID] instruction_form[self.OPERANDS_ID] = result[self.OPERANDS_ID] instruction_form[self.COMMENT_ID] = result[self.COMMENT_ID] return instruction_form
def _get_directive(self, parser, directive): return AttrDict.convert_dict( parser.process_operand( parser.directive.parseString( directive, parseAll=True).asDict())).directive
def test_reg_dependency(self): reg_1_1 = AttrDict({'prefix': 'b', 'name': '1'}) reg_1_2 = AttrDict({'prefix': 'h', 'name': '1'}) reg_1_3 = AttrDict({'prefix': 's', 'name': '1'}) reg_1_4 = AttrDict({'prefix': 'd', 'name': '1'}) reg_1_4 = AttrDict({'prefix': 'q', 'name': '1'}) reg_2_1 = AttrDict({'prefix': 'w', 'name': '2'}) reg_2_2 = AttrDict({'prefix': 'x', 'name': '2'}) reg_v1_1 = AttrDict({ 'prefix': 'v', 'name': '11', 'lanes': '16', 'shape': 'b' }) reg_v1_2 = AttrDict({ 'prefix': 'v', 'name': '11', 'lanes': '8', 'shape': 'h' }) reg_v1_3 = AttrDict({ 'prefix': 'v', 'name': '11', 'lanes': '4', 'shape': 's' }) reg_v1_4 = AttrDict({ 'prefix': 'v', 'name': '11', 'lanes': '2', 'shape': 'd' }) reg_b5 = AttrDict({'prefix': 'b', 'name': '5'}) reg_q15 = AttrDict({'prefix': 'q', 'name': '15'}) reg_v10 = AttrDict({ 'prefix': 'v', 'name': '10', 'lanes': '2', 'shape': 's' }) reg_v20 = AttrDict({ 'prefix': 'v', 'name': '20', 'lanes': '2', 'shape': 'd' }) reg_1 = [reg_1_1, reg_1_2, reg_1_3, reg_1_4] reg_2 = [reg_2_1, reg_2_2] reg_v = [reg_v1_1, reg_v1_2, reg_v1_3, reg_v1_4] reg_others = [reg_b5, reg_q15, reg_v10, reg_v20] regs = reg_1 + reg_2 + reg_v + reg_others # test each register against each other for ri in reg_1: for rj in regs: assert_value = True if rj in reg_1 else False with self.subTest(reg_a=ri, reg_b=rj, assert_val=assert_value): self.assertEqual(self.parser.is_reg_dependend_of(ri, rj), assert_value) for ri in reg_2: for rj in regs: assert_value = True if rj in reg_2 else False with self.subTest(reg_a=ri, reg_b=rj, assert_val=assert_value): self.assertEqual(self.parser.is_reg_dependend_of(ri, rj), assert_value) for ri in reg_v: for rj in regs: assert_value = True if rj in reg_v else False with self.subTest(reg_a=ri, reg_b=rj, assert_val=assert_value): self.assertEqual(self.parser.is_reg_dependend_of(ri, rj), assert_value) for ri in reg_others: for rj in regs: assert_value = True if rj == ri else False with self.subTest(reg_a=ri, reg_b=rj, assert_val=assert_value): self.assertEqual(self.parser.is_reg_dependend_of(ri, rj), assert_value)
def test_is_read_is_written_AArch64(self): # independent form HW model dag = KernelDG(self.kernel_AArch64, self.parser_AArch64, None) reg_x1 = AttrDict({'prefix': 'x', 'name': '1'}) reg_w1 = AttrDict({'prefix': 'w', 'name': '1'}) reg_d1 = AttrDict({'prefix': 'd', 'name': '1'}) reg_q1 = AttrDict({'prefix': 'q', 'name': '1'}) reg_v1 = AttrDict({ 'prefix': 'v', 'name': '1', 'lanes': '2', 'shape': 'd' }) regs = [reg_d1, reg_q1, reg_v1] regs_gp = [reg_w1, reg_x1] instr_form_r_1 = self.parser_AArch64.parse_line( 'stp q1, q3, [x12, #192]') self.semantics_tx2.assign_src_dst(instr_form_r_1) instr_form_r_2 = self.parser_AArch64.parse_line( 'fadd v2.2d, v1.2d, v0.2d') self.semantics_tx2.assign_src_dst(instr_form_r_2) instr_form_w_1 = self.parser_AArch64.parse_line( 'ldr d1, [x1, #:got_lo12:q2c]') self.semantics_tx2.assign_src_dst(instr_form_w_1) instr_form_non_w_1 = self.parser_AArch64.parse_line( 'ldr x1, [x1, #:got_lo12:q2c]') self.semantics_tx2.assign_src_dst(instr_form_non_w_1) instr_form_rw_1 = self.parser_AArch64.parse_line( 'fmul v1.2d, v1.2d, v0.2d') self.semantics_tx2.assign_src_dst(instr_form_rw_1) instr_form_rw_2 = self.parser_AArch64.parse_line( 'ldp q2, q4, [x1, #64]!') self.semantics_tx2.assign_src_dst(instr_form_rw_2) instr_form_rw_3 = self.parser_AArch64.parse_line('str x4, [x1], #64') self.semantics_tx2.assign_src_dst(instr_form_rw_3) instr_form_non_rw_1 = self.parser_AArch64.parse_line('adds x1, x11') self.semantics_tx2.assign_src_dst(instr_form_non_rw_1) for reg in regs: with self.subTest(reg=reg): self.assertTrue(dag.is_read(reg, instr_form_r_1)) self.assertTrue(dag.is_read(reg, instr_form_r_2)) self.assertTrue(dag.is_read(reg, instr_form_rw_1)) self.assertFalse(dag.is_read(reg, instr_form_rw_2)) self.assertFalse(dag.is_read(reg, instr_form_rw_3)) self.assertFalse(dag.is_read(reg, instr_form_w_1)) self.assertTrue(dag.is_written(reg, instr_form_w_1)) self.assertTrue(dag.is_written(reg, instr_form_rw_1)) self.assertFalse(dag.is_written(reg, instr_form_non_w_1)) self.assertFalse(dag.is_written(reg, instr_form_rw_2)) self.assertFalse(dag.is_written(reg, instr_form_rw_3)) self.assertFalse(dag.is_written(reg, instr_form_non_rw_1)) self.assertFalse(dag.is_written(reg, instr_form_non_rw_1)) for reg in regs_gp: with self.subTest(reg=reg): self.assertFalse(dag.is_read(reg, instr_form_r_1)) self.assertFalse(dag.is_read(reg, instr_form_r_2)) self.assertFalse(dag.is_read(reg, instr_form_rw_1)) self.assertTrue(dag.is_read(reg, instr_form_rw_2)) self.assertTrue(dag.is_read(reg, instr_form_rw_3)) self.assertTrue(dag.is_read(reg, instr_form_w_1)) self.assertFalse(dag.is_written(reg, instr_form_w_1)) self.assertFalse(dag.is_written(reg, instr_form_rw_1)) self.assertTrue(dag.is_written(reg, instr_form_non_w_1)) self.assertTrue(dag.is_written(reg, instr_form_rw_2)) self.assertTrue(dag.is_written(reg, instr_form_rw_3)) self.assertTrue(dag.is_written(reg, instr_form_non_rw_1)) self.assertTrue(dag.is_written(reg, instr_form_non_rw_1))
def _get_label(self, parser, label): return AttrDict.convert_dict( parser.process_operand( parser.label.parseString(label, parseAll=True).asDict())).label