From b469f5a0c4b3e2f083b227ff75661ffc10c05c19 Mon Sep 17 00:00:00 2001 From: JanLJL Date: Tue, 28 May 2019 18:22:28 +0200 Subject: [PATCH] added tests for pre/post-indexed addr and prefetching --- osaca/parser/parser_AArch64v81.py | 30 +++++------ tests/test_parser_AArch64v81.py | 82 ++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/osaca/parser/parser_AArch64v81.py b/osaca/parser/parser_AArch64v81.py index dde626e..a4c55e5 100755 --- a/osaca/parser/parser_AArch64v81.py +++ b/osaca/parser/parser_AArch64v81.py @@ -151,7 +151,7 @@ class ParserAArch64v81(BaseParser): ).setResultsName('prfop') # Combine to instruction form operand_first = pp.Group( - register ^ immediate ^ memory ^ arith_immediate ^ (prefetch_op | identifier) + register ^ (prefetch_op | immediate) ^ memory ^ arith_immediate ^ identifier ) operand_rest = pp.Group((register ^ immediate ^ memory ^ arith_immediate) | identifier) self.instruction_parser = ( @@ -165,14 +165,6 @@ class ParserAArch64v81(BaseParser): + pp.Optional(operand_rest.setResultsName('operand4')) + pp.Optional(self.comment) ) - self.opf = operand_first - self.opr = operand_rest - self.mem = memory - self.reg = register - self.idf = identifier - self.prfop = prefetch_op - self.imd = immediate - self.aimd = arith_immediate def parse_line(self, line, line_number=None): """ @@ -247,33 +239,33 @@ class ParserAArch64v81(BaseParser): def parse_instruction(self, instruction): result = self.instruction_parser.parseString(instruction, parseAll=True).asDict() operands = {'source': [], 'destination': []} - # ARM specific store flags + # ARM specific load store flags is_store = False - store_ex = False + is_load = False if result['mnemonic'].lower().startswith('st'): # Store instruction --> swap source and destination is_store = True - if result['mnemonic'].lower().startswith('strex'): - # Store exclusive --> first reg ist used for return state - store_ex = True + if result['mnemonic'].lower().startswith('ld'): + # Load instruction --> keep in mind for possible multiple loads + is_load = True # Check from left to right # Check first operand if 'operand1' in result: - if is_store and not store_ex: + if is_store: operands['source'].append(self._process_operand(result['operand1'])) else: operands['destination'].append(self._process_operand(result['operand1'])) # Check second operand if 'operand2' in result: - if is_store and 'operand3' not in result: + if is_store and 'operand3' not in result or is_load and 'operand3' in result: # destination operands['destination'].append(self._process_operand(result['operand2'])) else: operands['source'].append(self._process_operand(result['operand2'])) # Check third operand if 'operand3' in result: - if is_store and 'operand4' not in result: + if is_store and 'operand4' not in result or is_load and 'operand4' in result: operands['destination'].append(self._process_operand(result['operand3'])) else: operands['source'].append(self._process_operand(result['operand3'])) @@ -320,6 +312,10 @@ class ParserAArch64v81(BaseParser): if memory_address['index']['shift_op'].lower() in valid_shift_ops: scale = str(2 ** int(memory_address['index']['shift']['value'])) new_dict = {'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 {'memory': new_dict} def substitute_register_list(self, register_list): diff --git a/tests/test_parser_AArch64v81.py b/tests/test_parser_AArch64v81.py index 8d20876..dd1bbfb 100755 --- a/tests/test_parser_AArch64v81.py +++ b/tests/test_parser_AArch64v81.py @@ -143,7 +143,9 @@ class TestParserAArch64v81(unittest.TestCase): line_label = '.LBB0_1: // =>This Inner Loop Header: Depth=1' line_directive = '\t.cfi_def_cfa w29, -16' line_instruction = '\tldr s0, [x11, w10, sxtw #2]\t\t// = <<2' - # STREXD/STREX/STRD? + line_prefetch = 'prfm pldl1keep, [x26, #2048] //HPL' + line_preindexed = 'stp x29, x30, [sp, #-16]!' + line_postindexed = 'ldp q2, q3, [x11], #64' instruction_form_1 = { 'instruction': None, @@ -195,15 +197,91 @@ class TestParserAArch64v81(unittest.TestCase): 'label': None, 'line_number': 4, } + instruction_form_5 = { + 'instruction': 'prfm', + 'operands': { + 'source': [ + { + 'memory': { + 'offset': {'value': '2048'}, + 'base': {'prefix': 'x', 'name': '26'}, + 'index': None, + 'scale': '1', + } + } + ], + 'destination': [ + {'prfop': {'type': ['PLD'], 'target': ['L1'], 'policy': ['KEEP']}} + ], + }, + 'directive': None, + 'comment': 'HPL', + 'label': None, + 'line_number': 5, + } + instruction_form_6 = { + 'instruction': 'stp', + 'operands': { + 'source': [ + {'register': {'prefix': 'x', 'name': '29'}}, + {'register': {'prefix': 'x', 'name': '30'}} + ], + 'destination': [ + { + 'memory': { + 'offset': {'value': '-16'}, + 'base': {'name': 'sp', 'prefix': None}, + 'index': None, + 'scale': '1', + 'pre-indexed': True + } + } + ], + }, + 'directive': None, + 'comment': None, + 'label': None, + 'line_number': 6 + } + instruction_form_7 = { + 'instruction': 'ldp', + 'operands': { + 'source': [ + { + 'memory': { + 'offset': None, + 'base': {'prefix': 'x', 'name': '11'}, + 'index': None, + 'scale': '1', + 'post-indexed': {'value': '64'}, + } + } + ], + 'destination': [ + {'register': {'prefix': 'q', 'name': '2'}}, + {'register': {'prefix': 'q', 'name': '3'}}, + ], + }, + 'directive': None, + 'comment': None, + 'label': None, + 'line_number': 7, + } parsed_1 = self.parser.parse_line(line_comment, 1) parsed_2 = self.parser.parse_line(line_label, 2) parsed_3 = self.parser.parse_line(line_directive, 3) parsed_4 = self.parser.parse_line(line_instruction, 4) + parsed_5 = self.parser.parse_line(line_prefetch, 5) + parsed_6 = self.parser.parse_line(line_preindexed, 6) + parsed_7 = self.parser.parse_line(line_postindexed, 7) self.assertEqual(parsed_1, instruction_form_1) self.assertEqual(parsed_2, instruction_form_2) self.assertEqual(parsed_3, instruction_form_3) - self.assertEqual(parsed_4['operands'], instruction_form_4['operands']) + self.assertEqual(parsed_4, instruction_form_4) + self.assertEqual(parsed_5, instruction_form_5) + self.assertEqual(parsed_6, instruction_form_6) + self.assertEqual(parsed_7, instruction_form_7) def test_parse_file(self): parsed = self.parser.parse_file(self.triad_code)