added tests for pre/post-indexed addr and prefetching

This commit is contained in:
JanLJL
2019-05-28 18:22:28 +02:00
parent f7ce5ac63c
commit b469f5a0c4
2 changed files with 93 additions and 19 deletions

View File

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

View File

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