diff --git a/osaca/parser/parser_AArch64.py b/osaca/parser/parser_AArch64.py index bccaa2a..d75d3ed 100755 --- a/osaca/parser/parser_AArch64.py +++ b/osaca/parser/parser_AArch64.py @@ -91,31 +91,49 @@ class ParserAArch64(BaseParser): ^ pp.CaselessLiteral('ror') ^ pp.CaselessLiteral('sxtw') ^ pp.CaselessLiteral('uxtw') + ^ pp.CaselessLiteral('mul vl') ) arith_immediate = pp.Group( immediate.setResultsName('base_immediate') + pp.Suppress(pp.Literal(',')) + shift_op.setResultsName('shift_op') - + immediate.setResultsName('shift') + + pp.Optional(immediate).setResultsName('shift') ).setResultsName(self.IMMEDIATE_ID) # Register: - # scalar: [XWBHSDQ][0-9]{1,2} | vector: V[0-9]{1,2}\.[12468]{1,2}[BHSD]()? - # define SP and ZR register aliases as regex, due to pyparsing does not support + # scalar: [XWBHSDQ][0-9]{1,2} | vector: [VZ][0-9]{1,2}(\.[12468]{1,2}[BHSD])? + # | predicate: P[0-9]{1,2}(/[ZM])? + # ignore vector len control ZCR_EL[123] for now + # define SP, ZR register aliases as regex, due to pyparsing does not support # proper lookahead alias_r31_sp = pp.Regex('(?P[a-zA-Z])?(?P(sp|SP))') alias_r31_zr = pp.Regex('(?P[a-zA-Z])?(?P(zr|ZR))') - scalar = pp.Word(pp.alphas, exact=1).setResultsName('prefix') + pp.Word( + scalar = pp.Word('xwbhsdqXWBHSDQ', exact=1).setResultsName('prefix') + pp.Word( pp.nums ).setResultsName('name') index = pp.Literal('[') + pp.Word(pp.nums).setResultsName('index') + pp.Literal(']') vector = ( - pp.CaselessLiteral('v').setResultsName('prefix') + pp.oneOf('v z', caseless=True).setResultsName('prefix') + pp.Word(pp.nums).setResultsName('name') + pp.Literal('.') + pp.Optional(pp.Word('12468')).setResultsName('lanes') + pp.Word(pp.alphas, exact=1).setResultsName('shape') + pp.Optional(index) ) + predicate = ( + pp.CaselessLiteral('p').setResultsName('prefix') + + pp.Word(pp.nums).setResultsName('name') + + pp.Optional( + ( + pp.Suppress(pp.Literal('/')) + + pp.oneOf('z m', caseless=True).setResultsName('predication') + ) + | ( + pp.Literal('.') + + pp.Optional(pp.Word('12468')).setResultsName('lanes') + + pp.Word(pp.alphas, exact=1).setResultsName('shape') + ) + ) + ) self.list_element = vector ^ scalar register_list = ( pp.Literal('{') @@ -129,7 +147,8 @@ class ParserAArch64(BaseParser): + pp.Optional(index) ) register = pp.Group( - (alias_r31_sp | alias_r31_zr | vector | scalar | register_list) + (alias_r31_sp | alias_r31_zr | vector | scalar | predicate | register_list) + #(alias_r31_sp | alias_r31_zr | vector | scalar | predicate | register_list) + pp.Optional( pp.Suppress(pp.Literal(',')) + shift_op.setResultsName('shift_op') @@ -144,7 +163,7 @@ class ParserAArch64(BaseParser): pp.Literal('[') + pp.Optional(register.setResultsName('base')) + pp.Optional(pp.Suppress(pp.Literal(','))) - + pp.Optional(register_index ^ immediate.setResultsName('offset')) + + pp.Optional(register_index ^ (immediate ^ arith_immediate).setResultsName('offset')) + pp.Literal(']') + pp.Optional( pp.Literal('!').setResultsName('pre_indexed') @@ -177,6 +196,11 @@ class ParserAArch64(BaseParser): + pp.Optional(self.comment) ) + # for testing + self.predicate = predicate + self.vector = vector + self.register = register + def parse_line(self, line, line_number=None): """ Parse line and return instruction form. @@ -193,7 +217,7 @@ class ParserAArch64(BaseParser): self.DIRECTIVE_ID: None, self.COMMENT_ID: None, self.LABEL_ID: None, - 'line': line.strip(), + 'line': line.strip().replace('\t',' '), 'line_number': line_number, } ) @@ -351,18 +375,20 @@ class ParserAArch64(BaseParser): 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 - vlist = [] + rlist = [] dict_name = '' if 'list' in register_list: dict_name = 'list' if 'range' in register_list: dict_name = 'range' - for v in register_list[dict_name]: - vlist.append( - AttrDict.convert_dict(self.list_element.parseString(v, parseAll=True).asDict()) + for r in register_list[dict_name]: + rlist.append( + AttrDict.convert_dict(self.list_element.parseString(r, parseAll=True).asDict()) ) index = None if 'index' not in register_list else register_list['index'] - new_dict = AttrDict({dict_name: vlist, 'index': index}) + 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 process_immediate(self, immediate): @@ -440,7 +466,7 @@ class ParserAArch64(BaseParser): def is_vector_register(self, register): """Check if register is a vector register""" - if register['prefix'] in 'bhsdqv': + if register['prefix'] in 'bhsdqvz': return True return False @@ -455,7 +481,7 @@ class ParserAArch64(BaseParser): def is_reg_dependend_of(self, reg_a, reg_b): """Check if ``reg_a`` is dependent on ``reg_b``""" prefixes_gpr = 'wx' - prefixes_vec = 'bhsdqv' + prefixes_vec = 'bhsdqvz' if reg_a['name'] == reg_b['name']: if reg_a['prefix'].lower() in prefixes_gpr and reg_b['prefix'].lower() in prefixes_gpr: return True