mirror of
https://github.com/RRZE-HPC/OSACA.git
synced 2026-01-04 10:10:08 +01:00
Merge branch 'master' into merge-branch
This commit is contained in:
@@ -26,7 +26,7 @@ __all__ = [
|
|||||||
|
|
||||||
def get_parser(isa, syntax="ATT"):
|
def get_parser(isa, syntax="ATT"):
|
||||||
if isa.lower() == "x86":
|
if isa.lower() == "x86":
|
||||||
return ParserX86ATT() if syntax == "ATT" else ParserX86Intel()
|
return ParserX86ATT() if syntax.upper() == "ATT" else ParserX86Intel()
|
||||||
elif isa.lower() == "aarch64":
|
elif isa.lower() == "aarch64":
|
||||||
return ParserAArch64()
|
return ParserAArch64()
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -170,16 +170,18 @@ class ParserAArch64(BaseParser):
|
|||||||
+ pp.Optional(immediate).setResultsName("shift")
|
+ pp.Optional(immediate).setResultsName("shift")
|
||||||
).setResultsName(self.immediate_id)
|
).setResultsName(self.immediate_id)
|
||||||
# Register:
|
# Register:
|
||||||
# scalar: [XWBHSDQ][0-9]{1,2} | vector: [VZ][0-9]{1,2}(\.[12468]{1,2}[BHSD])?
|
# scalar: [XWBHSDQ][0-9]{1,2}! | vector: [VZ][0-9]{1,2}(\.[12468]{1,2}[BHSD])?
|
||||||
# | predicate: P[0-9]{1,2}(/[ZM])?
|
# | predicate: P[0-9]{1,2}(/[ZM])?
|
||||||
# ignore vector len control ZCR_EL[123] for now
|
# ignore vector len control ZCR_EL[123] for now
|
||||||
# define SP, ZR register aliases as regex, due to pyparsing does not support
|
# define SP, ZR register aliases as regex, due to pyparsing does not support
|
||||||
# proper lookahead
|
# proper lookahead
|
||||||
alias_r31_sp = pp.Regex("(?P<prefix>[a-zA-Z])?(?P<name>(sp|SP))")
|
alias_r31_sp = pp.Regex("(?P<prefix>[a-zA-Z])?(?P<name>(sp|SP))")
|
||||||
alias_r31_zr = pp.Regex("(?P<prefix>[a-zA-Z])?(?P<name>(zr|ZR))")
|
alias_r31_zr = pp.Regex("(?P<prefix>[a-zA-Z])?(?P<name>(zr|ZR))")
|
||||||
scalar = pp.Word("xwbhsdqXWBHSDQ", exact=1).setResultsName("prefix") + pp.Word(
|
scalar = (
|
||||||
pp.nums
|
pp.Word("xwbhsdqXWBHSDQ", exact=1).setResultsName("prefix")
|
||||||
).setResultsName("name")
|
+ pp.Word(pp.nums).setResultsName("name")
|
||||||
|
+ pp.Optional(pp.Literal("!")).setResultsName("pre_indexed")
|
||||||
|
)
|
||||||
index = pp.Literal("[") + pp.Word(pp.nums).setResultsName("index") + pp.Literal("]")
|
index = pp.Literal("[") + pp.Word(pp.nums).setResultsName("index") + pp.Literal("]")
|
||||||
vector = (
|
vector = (
|
||||||
pp.oneOf("v z", caseless=True).setResultsName("prefix")
|
pp.oneOf("v z", caseless=True).setResultsName("prefix")
|
||||||
@@ -463,6 +465,7 @@ class ParserAArch64(BaseParser):
|
|||||||
lanes=operand["lanes"] if "lanes" in operand else None,
|
lanes=operand["lanes"] if "lanes" in operand else None,
|
||||||
index=operand["index"] if "index" in operand else None,
|
index=operand["index"] if "index" in operand else None,
|
||||||
predication=operand["predication"].lower() if "predication" in operand else None,
|
predication=operand["predication"].lower() if "predication" in operand else None,
|
||||||
|
pre_indexed=True if "pre_indexed" in operand else False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_memory_address(self, memory_address):
|
def process_memory_address(self, memory_address):
|
||||||
|
|||||||
@@ -87,6 +87,22 @@ class ISASemantics(object):
|
|||||||
instruction_form
|
instruction_form
|
||||||
)
|
)
|
||||||
op_dict["src_dst"] = []
|
op_dict["src_dst"] = []
|
||||||
|
# handle Xd! registers in aarch64
|
||||||
|
if any(
|
||||||
|
[
|
||||||
|
isinstance(op, RegisterOperand) and op.pre_indexed
|
||||||
|
for op in instruction_form.operands
|
||||||
|
]
|
||||||
|
):
|
||||||
|
src_dst_regs = [
|
||||||
|
op
|
||||||
|
for op in instruction_form.operands
|
||||||
|
if (isinstance(op, RegisterOperand) and op.pre_indexed)
|
||||||
|
]
|
||||||
|
for reg in src_dst_regs:
|
||||||
|
if reg in op_dict["source"]:
|
||||||
|
op_dict["source"].remove(reg)
|
||||||
|
op_dict["src_dst"].append(reg)
|
||||||
# post-process pre- and post-indexing for aarch64 memory operands
|
# post-process pre- and post-indexing for aarch64 memory operands
|
||||||
if self._parser.isa() == "aarch64":
|
if self._parser.isa() == "aarch64":
|
||||||
for operand in [op for op in op_dict["source"] if isinstance(op, MemoryOperand)]:
|
for operand in [op for op in op_dict["source"] if isinstance(op, MemoryOperand)]:
|
||||||
@@ -178,7 +194,11 @@ class ISASemantics(object):
|
|||||||
|
|
||||||
base_name = (o.base.prefix if o.base.prefix is not None else "") + o.base.name
|
base_name = (o.base.prefix if o.base.prefix is not None else "") + o.base.name
|
||||||
reg_operand_names = {base_name: "op1"}
|
reg_operand_names = {base_name: "op1"}
|
||||||
operand_state = {"op1": {"name": base_name, "value": o.offset.value}}
|
if o.offset:
|
||||||
|
operand_state = {"op1": {"name": base_name, "value": o.offset.value}}
|
||||||
|
else:
|
||||||
|
# no offset (e.g., with Arm9 memops) -> base is updated
|
||||||
|
operand_state = {"op1": None}
|
||||||
|
|
||||||
if isa_data is not None and isa_data.operation is not None:
|
if isa_data is not None and isa_data.operation is not None:
|
||||||
for i, o in enumerate(instruction_form.operands):
|
for i, o in enumerate(instruction_form.operands):
|
||||||
|
|||||||
8
tests/test_files/mops_aarch64.s
Normal file
8
tests/test_files/mops_aarch64.s
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
memprolog [x3]!, [x1]!, x2!
|
||||||
|
//ALT1 ldp x3,x1, [sp, #40]
|
||||||
|
memmain [x3]!, [x1]!, x2!
|
||||||
|
//ALT1 ldp x3,x1, [sp, #40]
|
||||||
|
memepilog [x3]!, [x1]!, x2!
|
||||||
|
//ALT1 ldp x3,x1, [sp, #40]
|
||||||
|
//ALT1 memprolog [x3]!, x2!, x1
|
||||||
|
add x2, x2, #123
|
||||||
@@ -23,6 +23,9 @@ class TestParserAArch64(unittest.TestCase):
|
|||||||
self.parser = ParserAArch64()
|
self.parser = ParserAArch64()
|
||||||
with open(self._find_file("triad_arm_iaca.s")) as f:
|
with open(self._find_file("triad_arm_iaca.s")) as f:
|
||||||
self.triad_code = f.read()
|
self.triad_code = f.read()
|
||||||
|
with open(self._find_file("mops_aarch64.s")) as f:
|
||||||
|
self.mops_1_code = f.read()
|
||||||
|
self.mops_2_code = self.mops_1_code.replace("//ALT1 ", "")
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Test
|
# Test
|
||||||
@@ -173,6 +176,12 @@ class TestParserAArch64(unittest.TestCase):
|
|||||||
self.assertEqual(parsed_9.operands[0].prefix, "x")
|
self.assertEqual(parsed_9.operands[0].prefix, "x")
|
||||||
self.assertEqual(parsed_9.operands[3].ccode, "CC")
|
self.assertEqual(parsed_9.operands[3].ccode, "CC")
|
||||||
|
|
||||||
|
def test_mops(self):
|
||||||
|
parsed_1 = self.parser.parse_file(self.mops_1_code)
|
||||||
|
parsed_2 = self.parser.parse_file(self.mops_1_code)
|
||||||
|
self.assertEqual(len(parsed_1), 8)
|
||||||
|
self.assertEqual(len(parsed_2), 8)
|
||||||
|
|
||||||
def test_parse_line(self):
|
def test_parse_line(self):
|
||||||
line_comment = "// -- Begin main"
|
line_comment = "// -- Begin main"
|
||||||
line_label = ".LBB0_1: // =>This Inner Loop Header: Depth=1"
|
line_label = ".LBB0_1: // =>This Inner Loop Header: Depth=1"
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ class TestSemanticTools(unittest.TestCase):
|
|||||||
cls.code_AArch64_SVE = f.read()
|
cls.code_AArch64_SVE = f.read()
|
||||||
with open(cls._find_file("kernel_aarch64_deps.s")) as f:
|
with open(cls._find_file("kernel_aarch64_deps.s")) as f:
|
||||||
cls.code_AArch64_deps = f.read()
|
cls.code_AArch64_deps = f.read()
|
||||||
|
with open(cls._find_file("mops_aarch64.s")) as f:
|
||||||
|
cls.mops_1_code = f.read()
|
||||||
|
cls.mops_2_code = cls.mops_1_code.replace("//ALT1 ", "")
|
||||||
|
|
||||||
cls.kernel_x86 = reduce_to_section(
|
cls.kernel_x86 = reduce_to_section(
|
||||||
cls.parser_x86_att.parse_file(cls.code_x86), cls.parser_x86_att
|
cls.parser_x86_att.parse_file(cls.code_x86), cls.parser_x86_att
|
||||||
)
|
)
|
||||||
@@ -549,6 +553,56 @@ class TestSemanticTools(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
# TODO check for correct analysis
|
# TODO check for correct analysis
|
||||||
|
|
||||||
|
def test_mops_deps_AArch64(self):
|
||||||
|
self.kernel_mops_1 = reduce_to_section(
|
||||||
|
self.parser_AArch64.parse_file(self.mops_1_code), self.parser_AArch64
|
||||||
|
)
|
||||||
|
self.kernel_mops_2 = reduce_to_section(
|
||||||
|
self.parser_AArch64.parse_file(self.mops_2_code), self.parser_AArch64
|
||||||
|
)
|
||||||
|
self.semantics_a64fx.normalize_instruction_forms(self.kernel_mops_1)
|
||||||
|
self.semantics_a64fx.normalize_instruction_forms(self.kernel_mops_2)
|
||||||
|
for i in range(len(self.kernel_mops_1)):
|
||||||
|
self.semantics_a64fx.assign_src_dst(self.kernel_mops_1[i])
|
||||||
|
for i in range(len(self.kernel_mops_2)):
|
||||||
|
self.semantics_a64fx.assign_src_dst(self.kernel_mops_2[i])
|
||||||
|
|
||||||
|
mops_dest = MemoryOperand(
|
||||||
|
offset=None,
|
||||||
|
base=RegisterOperand(prefix="x", name="3"),
|
||||||
|
index=None,
|
||||||
|
scale=1,
|
||||||
|
pre_indexed=True,
|
||||||
|
)
|
||||||
|
mops_src = MemoryOperand(
|
||||||
|
offset=None,
|
||||||
|
base=RegisterOperand(prefix="x", name="1"),
|
||||||
|
index=None,
|
||||||
|
scale=1,
|
||||||
|
pre_indexed=True,
|
||||||
|
)
|
||||||
|
mops_n = RegisterOperand(prefix="x", name="2", pre_indexed=True)
|
||||||
|
mops_x1 = RegisterOperand(prefix="x", name="1")
|
||||||
|
for instruction_form in self.kernel_mops_1[:-1]:
|
||||||
|
with self.subTest(instruction_form=instruction_form):
|
||||||
|
if not instruction_form.line.startswith("//"):
|
||||||
|
self.assertTrue(mops_dest in instruction_form.semantic_operands["destination"])
|
||||||
|
self.assertTrue(mops_src in instruction_form.semantic_operands["source"])
|
||||||
|
self.assertTrue(mops_n in instruction_form.semantic_operands["src_dst"])
|
||||||
|
self.assertTrue(
|
||||||
|
mops_dest.base in instruction_form.semantic_operands["src_dst"]
|
||||||
|
)
|
||||||
|
self.assertTrue(mops_src.base in instruction_form.semantic_operands["src_dst"])
|
||||||
|
for instruction_form in self.kernel_mops_2[-2:-1]:
|
||||||
|
with self.subTest(instruction_form=instruction_form):
|
||||||
|
if not instruction_form.line.startswith("//"):
|
||||||
|
self.assertTrue(mops_dest in instruction_form.semantic_operands["destination"])
|
||||||
|
self.assertTrue(mops_x1 in instruction_form.semantic_operands["source"])
|
||||||
|
self.assertTrue(mops_n in instruction_form.semantic_operands["src_dst"])
|
||||||
|
self.assertTrue(
|
||||||
|
mops_dest.base in instruction_form.semantic_operands["src_dst"]
|
||||||
|
)
|
||||||
|
|
||||||
def test_hidden_load(self):
|
def test_hidden_load(self):
|
||||||
machine_model_hld = MachineModel(
|
machine_model_hld = MachineModel(
|
||||||
path_to_yaml=self._find_file("hidden_load_machine_model.yml")
|
path_to_yaml=self._find_file("hidden_load_machine_model.yml")
|
||||||
|
|||||||
Reference in New Issue
Block a user