supports hidden operands now (for flags or special instructions)

This commit is contained in:
JanLJL
2020-01-14 20:54:00 +01:00
parent 3ff8a695b6
commit 76469f7898
4 changed files with 52 additions and 4 deletions

View File

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

View File

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

View File

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

View File

@@ -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 = (