diff --git a/osaca/parser/parser_AArch64v81.py b/osaca/parser/parser_AArch64v81.py index 6d7b46e..83818aa 100755 --- a/osaca/parser/parser_AArch64v81.py +++ b/osaca/parser/parser_AArch64v81.py @@ -408,6 +408,13 @@ class ParserAArch64v81(BaseParser): return True return False + def is_flag_dependend_of(self, flag_a, flag_b): + # we assume flags are independent of each other, e.g., CF can be read while ZF gets written + # TODO validate this assumption + if flag_a.name == flag_b.name: + return True + return False + def is_reg_dependend_of(self, reg_a, reg_b): prefixes_gpr = 'wx' prefixes_vec = 'bhsdqv' diff --git a/osaca/parser/parser_x86att.py b/osaca/parser/parser_x86att.py index 3bc8bba..e680521 100755 --- a/osaca/parser/parser_x86att.py +++ b/osaca/parser/parser_x86att.py @@ -295,6 +295,13 @@ class ParserX86ATT(BaseParser): # identifier return imd + def is_flag_dependend_of(self, flag_a, flag_b): + # we assume flags are independent of each other, e.g., CF can be read while ZF gets written + # TODO validate this assumption + if flag_a.name == flag_b.name: + return True + return False + def is_reg_dependend_of(self, reg_a, reg_b): # Check if they are the same registers if reg_a.name == reg_b.name: diff --git a/osaca/semantics/isa_semantics.py b/osaca/semantics/isa_semantics.py index 7e97b77..aa5141e 100755 --- a/osaca/semantics/isa_semantics.py +++ b/osaca/semantics/isa_semantics.py @@ -86,6 +86,23 @@ class ISASemantics(object): 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) # post-process pre- and post-indexing for aarch64 memory operands if self._isa == 'aarch64': for operand in [op for op in op_dict['source'] if 'memory' in op]: diff --git a/osaca/semantics/kernel_dg.py b/osaca/semantics/kernel_dg.py index 3e41579..6b46156 100755 --- a/osaca/semantics/kernel_dg.py +++ b/osaca/semantics/kernel_dg.py @@ -6,7 +6,7 @@ from itertools import chain, product import networkx as nx from osaca.parser import AttrDict -from osaca.semantics import MachineModel +from osaca.semantics import INSTR_FLAGS, MachineModel class KernelDG(nx.DiGraph): @@ -26,10 +26,9 @@ class KernelDG(nx.DiGraph): dg.add_node(instruction_form['line_number']) dg.nodes[instruction_form['line_number']]['instruction_form'] = instruction_form # add load as separate node if existent - # TODO use INSTR_FLAGS here if ( - 'performs_load' in instruction_form['flags'] - and 'is_load_instruction' not in instruction_form['flags'] + INSTR_FLAGS.HAS_LD in instruction_form['flags'] + and INSTR_FLAGS.LD not in instruction_form['flags'] ): # add new node dg.add_node(instruction_form['line_number'] + 0.1) @@ -167,6 +166,20 @@ class KernelDG(nx.DiGraph): if include_write: yield instr_form break + if 'flag' in dst: + # Check for read of flag until overwrite + for instr_form in kernel: + if self.is_read(dst.flag, instr_form): + yield instr_form + if self.is_written(dst.flag, instr_form): + # operand in src_dst list + if include_write: + yield instr_form + break + elif self.is_written(dst.flag, instr_form): + if include_write: + yield instr_form + break elif 'memory' in dst: # Check if base register is altered during memory access if 'pre_indexed' in dst.memory or 'post_indexed' in dst.memory: @@ -206,6 +219,8 @@ class KernelDG(nx.DiGraph): instruction_form.semantic_operands.src_dst): if 'register' in src: is_read = self.parser.is_reg_dependend_of(register, src.register) or is_read + if 'flag' in src: + is_read = self.parser.is_flag_dependend_of(register, src.flag) or is_read if 'memory' in src: if src.memory.base is not None: is_read = self.parser.is_reg_dependend_of(register, src.memory.base) or is_read @@ -233,6 +248,8 @@ class KernelDG(nx.DiGraph): instruction_form.semantic_operands.src_dst): if 'register' in dst: is_written = self.parser.is_reg_dependend_of(register, dst.register) or is_written + if 'flag' in dst: + is_written = self.parser.is_flag_dependend_of(register, dst.flag) or is_written if 'memory' in dst: if 'pre_indexed' in dst.memory or 'post_indexed' in dst.memory: is_written = (