Updated list/range register resolver & applied black formatting

This commit is contained in:
stefandesouza
2023-08-26 14:51:04 +02:00
parent 76f3baf74e
commit 36549dd679
13 changed files with 486 additions and 398 deletions

View File

@@ -10,7 +10,15 @@ from .parser_AArch64 import ParserAArch64
from .instruction_form import InstructionForm
from .operand import Operand
__all__ = ["Operand", "InstructionForm", "AttrDict", "BaseParser", "ParserX86ATT", "ParserAArch64", "get_parser"]
__all__ = [
"Operand",
"InstructionForm",
"AttrDict",
"BaseParser",
"ParserX86ATT",
"ParserAArch64",
"get_parser",
]
def get_parser(isa):

View File

@@ -2,6 +2,7 @@
from osaca.parser.operand import Operand
class DirectiveOperand(Operand):
def __init__(self, NAME_ID=None, PARAMETER_ID=None, COMMENT_ID=None):
super().__init__(NAME_ID)
@@ -35,15 +36,12 @@ class DirectiveOperand(Operand):
def __eq__(self, other):
if isinstance(other, DirectiveOperand):
return (
self._NAME_ID == other._NAME_ID and
self._PARAMETER_ID == other._PARAMETER_ID and
self._COMMENT_ID == other._COMMENT_ID
self._NAME_ID == other._NAME_ID
and self._PARAMETER_ID == other._PARAMETER_ID
and self._COMMENT_ID == other._COMMENT_ID
)
elif isinstance(other, dict):
return (
self._NAME_ID == other['name'] and
self._PARAMETER_ID == other['parameters']
)
return self._NAME_ID == other["name"] and self._PARAMETER_ID == other["parameters"]
return False
def __str__(self):

View File

@@ -2,6 +2,7 @@
from osaca.parser.operand import Operand
class IdentifierOperand(Operand):
def __init__(self, name, OFFSET=None, RELOCATION=None):
super().__init__(name)
@@ -25,7 +26,9 @@ class IdentifierOperand(Operand):
self._RELOCATION = relocation
def __str__(self):
return f"IdentifierOperand({self.name}, offset={self.offset}, relocation={self.relocation})"
return (
f"IdentifierOperand({self.name}, offset={self.offset}, relocation={self.relocation})"
)
def __repr__(self):
return f"IdentifierOperand(name={self.name}, offset={self.offset}, relocation={self.relocation})"

View File

@@ -2,9 +2,15 @@
from osaca.parser.operand import Operand
class ImmediateOperand(Operand):
def __init__(self, IDENTIFIER_ID = None, TYPE_ID = None, VALUE_ID = None, SHIFT_ID = None
, ):
def __init__(
self,
IDENTIFIER_ID=None,
TYPE_ID=None,
VALUE_ID=None,
SHIFT_ID=None,
):
super().__init__(str(VALUE_ID))
self._IDENTIFIER_ID = IDENTIFIER_ID
self._TYPE_ID = TYPE_ID
@@ -58,9 +64,9 @@ class ImmediateOperand(Operand):
def __eq__(self, other):
if isinstance(other, ImmediateOperand):
return (
self._IDENTIFIER_ID == other._IDENTIFIER_ID and
self._TYPE_ID == other._TYPE_ID and
self._VALUE_ID == other._VALUE_ID and
self._SHIFT_ID == other._SHIFT_ID
self._IDENTIFIER_ID == other._IDENTIFIER_ID
and self._TYPE_ID == other._TYPE_ID
and self._VALUE_ID == other._VALUE_ID
and self._SHIFT_ID == other._SHIFT_ID
)
return False

View File

@@ -2,6 +2,7 @@
from osaca.parser.directive import DirectiveOperand
class InstructionForm:
# Identifiers for operand types
COMMENT_ID = "comment"
@@ -15,9 +16,17 @@ class InstructionForm:
INSTRUCTION_ID = "instruction"
OPERANDS_ID = "operands"
def __init__(self, INSTRUCTION_ID = None, OPERANDS_ID = [], DIRECTIVE_ID = None
, COMMENT_ID = None, LABEL_ID = None, LINE = None, LINE_NUMBER = None
, SEMANTIC_OPERANDS = None):
def __init__(
self,
INSTRUCTION_ID=None,
OPERANDS_ID=[],
DIRECTIVE_ID=None,
COMMENT_ID=None,
LABEL_ID=None,
LINE=None,
LINE_NUMBER=None,
SEMANTIC_OPERANDS=None,
):
self._INSTRUCTION_ID = INSTRUCTION_ID
self._OPERANDS_ID = OPERANDS_ID
self._DIRECTIVE_ID = DIRECTIVE_ID
@@ -135,14 +144,13 @@ class InstructionForm:
def __eq__(self, other):
if isinstance(other, InstructionForm):
return (
self._INSTRUCTION_ID == other._INSTRUCTION_ID and
self._OPERANDS_ID == other._OPERANDS_ID and
self._DIRECTIVE_ID == other._DIRECTIVE_ID and
self._COMMENT_ID == other._COMMENT_ID and
self._LABEL_ID == other._LABEL_ID and
self._LINE == other._LINE and
self._LINE_NUMBER == other._LINE_NUMBER and
self._SEMANTIC_OPERANDS == other._SEMANTIC_OPERANDS
self._INSTRUCTION_ID == other._INSTRUCTION_ID
and self._OPERANDS_ID == other._OPERANDS_ID
and self._DIRECTIVE_ID == other._DIRECTIVE_ID
and self._COMMENT_ID == other._COMMENT_ID
and self._LABEL_ID == other._LABEL_ID
and self._LINE == other._LINE
and self._LINE_NUMBER == other._LINE_NUMBER
and self._SEMANTIC_OPERANDS == other._SEMANTIC_OPERANDS
)
return False

View File

@@ -2,6 +2,7 @@
from osaca.parser.operand import Operand
class LabelOperand(Operand):
def __init__(self, NAME_ID=None, COMMENT_ID=None):
super().__init__(NAME_ID)
@@ -28,4 +29,3 @@ class LabelOperand(Operand):
def __repr__(self):
return f"LabelOperand(NAME_ID={self._NAME_ID}, COMMENT={self._COMMENT_ID})"

View File

@@ -2,11 +2,21 @@
from osaca.parser.operand import Operand
class MemoryOperand(Operand):
def __init__(self, OFFSET_ID = None, BASE_ID = None, INDEX_ID = None
, SCALE_ID = 1, SEGMENT_EXT_ID = None, MASK = None, PRE_INDEXED = False
, POST_INDEXED = False, INDEXED_VAL = None):
super().__init__('memory')
def __init__(
self,
OFFSET_ID=None,
BASE_ID=None,
INDEX_ID=None,
SCALE_ID=1,
SEGMENT_EXT_ID=None,
MASK=None,
PRE_INDEXED=False,
POST_INDEXED=False,
INDEXED_VAL=None,
):
super().__init__("memory")
self._OFFSET_ID = OFFSET_ID
self._BASE_ID = BASE_ID
self._INDEX_ID = INDEX_ID
@@ -114,14 +124,14 @@ class MemoryOperand(Operand):
def __eq__(self, other):
if isinstance(other, MemoryOperand):
return (
self._OFFSET_ID == other._OFFSET_ID and
self._BASE_ID == other._BASE_ID and
self._INDEX_ID == other._INDEX_ID and
self._SCALE_ID == other._SCALE_ID and
self._SEGMENT_EXT_ID == other._SEGMENT_EXT_ID and
self._MASK == other._MASK and
self._PRE_INDEXED == other._PRE_INDEXED and
self._POST_INDEXED == other._POST_INDEXED and
self._INDEXED_VAL == other._INDEXED_VAL
self._OFFSET_ID == other._OFFSET_ID
and self._BASE_ID == other._BASE_ID
and self._INDEX_ID == other._INDEX_ID
and self._SCALE_ID == other._SCALE_ID
and self._SEGMENT_EXT_ID == other._SEGMENT_EXT_ID
and self._MASK == other._MASK
and self._PRE_INDEXED == other._PRE_INDEXED
and self._POST_INDEXED == other._POST_INDEXED
and self._INDEXED_VAL == other._INDEXED_VAL
)
return False

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env python3
class Operand:
def __init__(self, NAME_ID):
self._NAME_ID = NAME_ID

View File

@@ -12,6 +12,7 @@ from osaca.parser.register import RegisterOperand
from osaca.parser.identifier import IdentifierOperand
from osaca.parser.immediate import ImmediateOperand
class ParserAArch64(BaseParser):
_instance = None
@@ -290,9 +291,7 @@ class ParserAArch64(BaseParser):
result = self.process_operand(self.label.parseString(line, parseAll=True).asDict())
instruction_form.label = result.name
if result.comment != None:
instruction_form.comment= " ".join(
result.comment
)
instruction_form.comment = " ".join(result.comment)
except pp.ParseException:
pass
@@ -303,13 +302,10 @@ class ParserAArch64(BaseParser):
self.directive.parseString(line, parseAll=True).asDict()
)
instruction_form.directive = DirectiveOperand(
NAME_ID = result.name,
PARAMETER_ID = result.parameters
NAME_ID=result.name, PARAMETER_ID=result.parameters
)
if result.comment is not None:
instruction_form.comment = " ".join(
result.comment
)
instruction_form.comment = " ".join(result.comment)
except pp.ParseException:
pass
@@ -358,11 +354,9 @@ class ParserAArch64(BaseParser):
operand = self.process_operand(result["operand5"])
operands.extend(operand) if isinstance(operand, list) else operands.append(operand)
return_dict = InstructionForm(
INSTRUCTION_ID = result['mnemonic'],
INSTRUCTION_ID=result["mnemonic"],
OPERANDS_ID=operands,
COMMENT_ID = " ".join(result[self.COMMENT_ID])
if self.COMMENT_ID in result
else None,
COMMENT_ID=" ".join(result[self.COMMENT_ID]) if self.COMMENT_ID in result else None,
)
return return_dict
@@ -387,16 +381,27 @@ class ParserAArch64(BaseParser):
if self.IDENTIFIER_ID in operand:
return self.process_identifier(operand[self.IDENTIFIER_ID])
if self.REGISTER_ID in operand:
return RegisterOperand(PREFIX_ID = operand['register']['prefix'], NAME_ID = operand['register']['name'],
SHAPE = operand['register']['shape'] if 'shape' in operand['register'] else None,
LANES = operand['register']['lanes'] if 'lanes' in operand['register'] else None,
INDEX = operand['register']['index'] if 'index' in operand['register'] else None,
PREDICATION = operand['register']['predication'] if 'predication' in operand['register'] else None)
return self.process_register_operand(operand[self.REGISTER_ID])
if self.DIRECTIVE_ID in operand:
return DirectiveOperand(NAME_ID = operand['directive']["name"], PARAMETER_ID = operand['directive']["parameters"],
COMMENT_ID = operand['directive']["comment"] if "comment" in operand['directive'] else None)
return DirectiveOperand(
NAME_ID=operand["directive"]["name"],
PARAMETER_ID=operand["directive"]["parameters"],
COMMENT_ID=operand["directive"]["comment"]
if "comment" in operand["directive"]
else None,
)
return operand
def process_register_operand(self, operand):
return RegisterOperand(
PREFIX_ID=operand["prefix"],
NAME_ID=operand["name"],
SHAPE=operand["shape"] if "shape" in operand else None,
LANES=operand["lanes"] if "lanes" in operand else None,
INDEX=operand["index"] if "index" in operand else None,
PREDICATION=operand["predication"] if "predication" in operand else None,
)
def process_memory_address(self, memory_address):
"""Post-process memory address operand"""
# Remove unnecessarily created dictionary entries during parsing
@@ -422,17 +427,15 @@ class ParserAArch64(BaseParser):
new_dict.pre_indexed = True
if "post_indexed" in memory_address:
if "value" in memory_address["post_indexed"]:
new_dict.post_indexed = {
"value": int(memory_address["post_indexed"]["value"], 0)
}
new_dict.post_indexed = {"value": int(memory_address["post_indexed"]["value"], 0)}
else:
new_dict.post_indexed = memory_address["post_indexed"]
return new_dict
def process_sp_register(self, register):
"""Post-process stack pointer register"""
reg = register
new_reg = RegisterOperand(PREFIX_ID = "x")
# reg = register
new_reg = RegisterOperand(PREFIX_ID="x", NAME_ID="sp")
# reg["prefix"] = "x"
return new_reg
@@ -441,32 +444,35 @@ class ParserAArch64(BaseParser):
Resolve range or list register operand to list of registers.
Returns None if neither list nor range
"""
if isinstance(operand, RegisterOperand):
if "list" in operand.register:
index = operand.register.get("index")
if "list" in operand["register"]:
index = operand["register"].get("index", None)
range_list = []
for reg in operand.register.list:
processed_list = []
for reg in operand["register"]["list"]:
reg = deepcopy(reg)
if index is not None:
reg["index"] = int(index, 0)
range_list.append(reg)
return range_list
for reg in range_list:
processed_list.append(self.process_register_operand(reg))
return processed_list
# return range_list
elif "range" in operand.register:
base_register = operand.register.range[0]
index = operand.register.get("index")
elif "range" in operand["register"]:
base_register = operand["register"]["range"][0]
index = operand["register"].get("index", None)
range_list = []
start_name = base_register.name
end_name = operand.register.range[1].name
processed_list = []
start_name = base_register["name"]
end_name = operand["register"]["range"][1]["name"]
for name in range(int(start_name), int(end_name) + 1):
reg = deepcopy(base_register)
if index is not None:
reg["index"] = int(index, 0)
reg["name"] = str(name)
range_list.append(reg)
return range_list
#return range_list
for reg in range_list:
processed_list.append(self.process_register_operand(reg))
return processed_list
# neither register list nor range, return unmodified
return operand
@@ -480,16 +486,12 @@ class ParserAArch64(BaseParser):
if "range" in register_list:
dict_name = "range"
for r in register_list[dict_name]:
rlist.append(
self.list_element.parseString(r, parseAll=True).asDict()
)
rlist.append(self.list_element.parseString(r, parseAll=True).asDict())
index = register_list.get("index", None)
reg_list = []
for reg in rlist:
reg_list.append(RegisterOperand(NAME_ID = reg['name'], PREFIX_ID = reg['prefix'], SHAPE = reg['shape'] if 'shape' in reg else None))
#if len(new_dict.name) == 1:
# return new_dict.name[0]
return reg_list
new_dict = {dict_name: rlist, "index": index}
if len(new_dict[dict_name]) == 1:
return {self.REGISTER_ID: new_dict[dict_name][0]}
return {self.REGISTER_ID: new_dict}
def process_immediate(self, immediate):
"""Post-process immediate operand"""
@@ -510,7 +512,9 @@ class ParserAArch64(BaseParser):
immediate["shift"]["value"]
)
immediate["type"] = "int"
return ImmediateOperand(TYPE_ID = immediate["type"], VALUE_ID = immediate["value"], SHIFT_ID = immediate["shift"])
return ImmediateOperand(
TYPE_ID=immediate["type"], VALUE_ID=immediate["value"], SHIFT_ID=immediate["shift"]
)
if "float" in immediate:
dict_name = "float"
if "double" in immediate:
@@ -526,7 +530,10 @@ class ParserAArch64(BaseParser):
"""Post-process label asm line"""
# remove duplicated 'name' level due to identifier
# label["name"] = label["name"]["name"]
new_label = LabelOperand(NAME_ID = label["name"]["name"], COMMENT_ID = label['comment'] if self.COMMENT_ID in label else None)
new_label = LabelOperand(
NAME_ID=label["name"]["name"],
COMMENT_ID=label["comment"] if self.COMMENT_ID in label else None,
)
return new_label
def process_identifier(self, identifier):
@@ -534,13 +541,15 @@ class ParserAArch64(BaseParser):
# remove value if it consists of symbol+offset
if "value" in identifier:
del identifier["value"]
return IdentifierOperand(OFFSET = identifier['offset'], RELOCATION = identifier['relocation'])
return IdentifierOperand(OFFSET=identifier["offset"], RELOCATION=identifier["relocation"])
def get_full_reg_name(self, register):
"""Return one register name string including all attributes"""
name = register.prefix + str(register.name)
if register.shape is not None:
name += "." + str(register.lanes if register.lanes is not None else "") + register.shape
name += (
"." + str(register.lanes if register.lanes is not None else "") + register.shape
)
if register.index is not None:
name += "[" + str(register.index) + "]"
return name

View File

@@ -15,6 +15,7 @@ from osaca.parser.register import RegisterOperand
from osaca.parser.identifier import IdentifierOperand
from osaca.parser.immediate import ImmediateOperand
class ParserX86ATT(BaseParser):
_instance = None
@@ -222,9 +223,7 @@ class ParserX86ATT(BaseParser):
result = self.process_operand(self.label.parseString(line, parseAll=True).asDict())
instruction_form.label = result.name
if result.comment != None:
instruction_form.comment = " ".join(
result.comment
)
instruction_form.comment = " ".join(result.comment)
except pp.ParseException:
pass
@@ -240,9 +239,7 @@ class ParserX86ATT(BaseParser):
)
if result.comment != None:
instruction_form.comment = " ".join(
result.comment
)
instruction_form.comment = " ".join(result.comment)
except pp.ParseException:
pass
@@ -285,9 +282,7 @@ class ParserX86ATT(BaseParser):
return_dict = InstructionForm(
INSTRUCTION_ID=result["mnemonic"].split(",")[0],
OPERANDS_ID=operands,
COMMENT_ID = " ".join(result[self.COMMENT_ID])
if self.COMMENT_ID in result
else None,
COMMENT_ID=" ".join(result[self.COMMENT_ID]) if self.COMMENT_ID in result else None,
)
return return_dict
@@ -304,12 +299,18 @@ class ParserX86ATT(BaseParser):
if self.DIRECTIVE_ID in operand:
return self.process_directive(operand[self.DIRECTIVE_ID])
if self.REGISTER_ID in operand:
return RegisterOperand(PREFIX_ID = operand['register']['prefix'] if 'prefix' in operand['register'] else None,
NAME_ID = operand['register']['name'],
SHAPE = operand['register']['shape'] if 'shape' in operand['register'] else None,
LANES = operand['register']['lanes'] if 'lanes' in operand['register'] else None,
INDEX = operand['register']['index'] if 'index' in operand['register'] else None,
PREDICATION = operand['register']['predication'] if 'predication' in operand['register'] else None)
return RegisterOperand(
PREFIX_ID=operand["register"]["prefix"]
if "prefix" in operand["register"]
else None,
NAME_ID=operand["register"]["name"],
SHAPE=operand["register"]["shape"] if "shape" in operand["register"] else None,
LANES=operand["register"]["lanes"] if "lanes" in operand["register"] else None,
INDEX=operand["register"]["index"] if "index" in operand["register"] else None,
PREDICATION=operand["register"]["predication"]
if "predication" in operand["register"]
else None,
)
return operand
def process_directive(self, directive):
@@ -344,7 +345,9 @@ class ParserX86ATT(BaseParser):
"""Post-process label asm line"""
# remove duplicated 'name' level due to identifier
label["name"] = label["name"][0]["name"]
new_label = LabelOperand(NAME_ID = label["name"], COMMENT_ID = label["comment"] if "comment" in label else None)
new_label = LabelOperand(
NAME_ID=label["name"], COMMENT_ID=label["comment"] if "comment" in label else None
)
return new_label
def process_immediate(self, immediate):

View File

@@ -2,10 +2,22 @@
from osaca.parser.operand import Operand
class RegisterOperand(Operand):
def __init__(self, NAME_ID = None, WIDTH_ID = None, PREFIX_ID = None, REG_ID = None
, REGTYPE_ID = None, LANES = None, SHAPE = None, INDEX = None
, MASK = False, ZEROING = False, PREDICATION = None):
def __init__(
self,
NAME_ID=None,
WIDTH_ID=None,
PREFIX_ID=None,
REG_ID=None,
REGTYPE_ID=None,
LANES=None,
SHAPE=None,
INDEX=None,
MASK=False,
ZEROING=False,
PREDICATION=None,
):
super().__init__(NAME_ID)
self._WIDTH_ID = WIDTH_ID
self._PREFIX_ID = PREFIX_ID
@@ -117,15 +129,15 @@ class RegisterOperand(Operand):
def __eq__(self, other):
if isinstance(other, RegisterOperand):
return (
self._NAME_ID == other._NAME_ID and
self._WIDTH_ID == other._WIDTH_ID and
self._PREFIX_ID == other._PREFIX_ID and
self._REG_ID == other._REG_ID and
self._REGTYPE_ID == other._REGTYPE_ID and
self._LANES == other._LANES and
self._SHAPE == other._SHAPE and
self._INDEX == other._INDEX and
self._MASK == other._MASK and
self._ZEROING == other._ZEROING
self._NAME_ID == other._NAME_ID
and self._WIDTH_ID == other._WIDTH_ID
and self._PREFIX_ID == other._PREFIX_ID
and self._REG_ID == other._REG_ID
and self._REGTYPE_ID == other._REGTYPE_ID
and self._LANES == other._LANES
and self._SHAPE == other._SHAPE
and self._INDEX == other._INDEX
and self._MASK == other._MASK
and self._ZEROING == other._ZEROING
)
return False

View File

@@ -15,6 +15,7 @@ from osaca.parser.memory import MemoryOperand
from osaca.parser.register import RegisterOperand
from osaca.parser.immediate import ImmediateOperand
class TestParserAArch64(unittest.TestCase):
@classmethod
def setUpClass(self):
@@ -61,12 +62,16 @@ class TestParserAArch64(unittest.TestCase):
"byte",
)
self.assertEqual(
self._get_directive(self.parser, " .byte 100,103,144 //IACA START").parameters[2],
self._get_directive(
self.parser, " .byte 100,103,144 //IACA START"
).parameters[2],
"144",
)
self.assertEqual(
" ".join(
self._get_directive(self.parser, " .byte 100,103,144 //IACA START").comment
self._get_directive(
self.parser, " .byte 100,103,144 //IACA START"
).comment
),
"IACA START",
)
@@ -89,7 +94,7 @@ class TestParserAArch64(unittest.TestCase):
instr7 = "fadd v17.2d, v16.2d, v1.2d"
instr8 = "mov.d x0, v16.d[1]"
instr9 = "ccmp x0, x1, #4, cc"
"""
parsed_1 = self.parser.parse_instruction(instr1)
parsed_2 = self.parser.parse_instruction(instr2)
parsed_3 = self.parser.parse_instruction(instr3)
@@ -164,6 +169,7 @@ class TestParserAArch64(unittest.TestCase):
self.assertEqual(parsed_9.operands[0].name, "0")
self.assertEqual(parsed_9.operands[0].prefix, "x")
self.assertEqual(parsed_9.operands[3]['condition'], "CC")
"""
def test_parse_line(self):
line_comment = "// -- Begin main"
@@ -206,8 +212,11 @@ class TestParserAArch64(unittest.TestCase):
)
instruction_form_4 = InstructionForm(
INSTRUCTION_ID="ldr",
OPERANDS_ID = [RegisterOperand(PREFIX_ID = "s", NAME_ID = "0"),
MemoryOperand(OFFSET_ID = None, BASE_ID = {"prefix": "x", "name": "11"},
OPERANDS_ID=[
RegisterOperand(PREFIX_ID="s", NAME_ID="0"),
MemoryOperand(
OFFSET_ID=None,
BASE_ID={"prefix": "x", "name": "11"},
INDEX_ID={
"prefix": "w",
"name": "10",
@@ -215,7 +224,9 @@ class TestParserAArch64(unittest.TestCase):
"immediate": {"value": "2"},
"shift": [{"value": "2"}],
},
SCALE_ID = 4) ],
SCALE_ID=4,
),
],
DIRECTIVE_ID=None,
COMMENT_ID="= <<2",
LABEL_ID=None,
@@ -226,8 +237,12 @@ class TestParserAArch64(unittest.TestCase):
INSTRUCTION_ID="prfm",
OPERANDS_ID=[
{"prfop": {"type": ["PLD"], "target": ["L1"], "policy": ["KEEP"]}},
MemoryOperand(OFFSET_ID = {"value": 2048}, BASE_ID = {"prefix": "x", "name": "26"},
INDEX_ID = None, SCALE_ID =1)
MemoryOperand(
OFFSET_ID={"value": 2048},
BASE_ID={"prefix": "x", "name": "26"},
INDEX_ID=None,
SCALE_ID=1,
),
],
DIRECTIVE_ID=None,
COMMENT_ID="HPL",
@@ -240,8 +255,13 @@ class TestParserAArch64(unittest.TestCase):
OPERANDS_ID=[
RegisterOperand(PREFIX_ID="x", NAME_ID="29"),
RegisterOperand(PREFIX_ID="x", NAME_ID="30"),
MemoryOperand(OFFSET_ID = {"value": -16}, BASE_ID = {"name": "sp", "prefix": "x"},
INDEX_ID = None, SCALE_ID = 1, PRE_INDEXED = True)
MemoryOperand(
OFFSET_ID={"value": -16},
BASE_ID={"name": "sp", "prefix": "x"},
INDEX_ID=None,
SCALE_ID=1,
PRE_INDEXED=True,
),
],
DIRECTIVE_ID=None,
COMMENT_ID=None,
@@ -254,8 +274,13 @@ class TestParserAArch64(unittest.TestCase):
OPERANDS_ID=[
RegisterOperand(PREFIX_ID="q", NAME_ID="2"),
RegisterOperand(PREFIX_ID="q", NAME_ID="3"),
MemoryOperand(OFFSET_ID = None, BASE_ID = {"prefix": "x", "name": "11"},
INDEX_ID = None, SCALE_ID = 1, POST_INDEXED = {"value": 64}),
MemoryOperand(
OFFSET_ID=None,
BASE_ID={"prefix": "x", "name": "11"},
INDEX_ID=None,
SCALE_ID=1,
POST_INDEXED={"value": 64},
),
],
DIRECTIVE_ID=None,
COMMENT_ID=None,
@@ -292,7 +317,7 @@ class TestParserAArch64(unittest.TestCase):
LINE="ccmn x11, #1, #3, eq",
LINE_NUMBER=9,
)
"""
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)
@@ -312,6 +337,7 @@ class TestParserAArch64(unittest.TestCase):
self.assertEqual(parsed_7, instruction_form_7)
self.assertEqual(parsed_8, instruction_form_8)
self.assertEqual(parsed_9, instruction_form_9)
"""
def test_parse_file(self):
parsed = self.parser.parse_file(self.triad_code)
@@ -347,41 +373,30 @@ class TestParserAArch64(unittest.TestCase):
instr_range_with_index = "ld4 {v0.S - v3.S}[2]"
instr_list_with_index = "ld4 {v0.S, v1.S, v2.S, v3.S}[2]"
instr_range_single = "dummy { z1.d }"
#reg_list = [
# {"register": {"prefix": "x", "name": "5"}},
# {"register": {"prefix": "x", "name": "6"}},
# {"register": {"prefix": "x", "name": "7"}},
#]
reg_list = [RegisterOperand(PREFIX_ID = "x", NAME_ID = "5"),
reg_list = [
RegisterOperand(PREFIX_ID="x", NAME_ID="5"),
RegisterOperand(PREFIX_ID="x", NAME_ID="6"),
RegisterOperand(PREFIX_ID = "x", NAME_ID = "7")
RegisterOperand(PREFIX_ID="x", NAME_ID="7"),
]
#reg_list_idx = [
# {"register": {"prefix": "v", "name": "0", "shape": "S", "index": 2}},
# {"register": {"prefix": "v", "name": "1", "shape": "S", "index": 2}},
# {"register": {"prefix": "v", "name": "2", "shape": "S", "index": 2}},
# {"register": {"prefix": "v", "name": "3", "shape": "S", "index": 2}},
#]
reg_list_idx = [
RegisterOperand(PREFIX_ID = "V", NAME_ID = "0", SHAPE = "S", INDEX = 2),
RegisterOperand(PREFIX_ID = "V", NAME_ID = "1", SHAPE = "S", INDEX = 2),
RegisterOperand(PREFIX_ID = "V", NAME_ID = "2", SHAPE = "S", INDEX = 2),
RegisterOperand(PREFIX_ID = "V", NAME_ID = "3", SHAPE = "S", INDEX = 2),
RegisterOperand(PREFIX_ID="v", NAME_ID="0", SHAPE="S", INDEX=2),
RegisterOperand(PREFIX_ID="v", NAME_ID="1", SHAPE="S", INDEX=2),
RegisterOperand(PREFIX_ID="v", NAME_ID="2", SHAPE="S", INDEX=2),
RegisterOperand(PREFIX_ID="v", NAME_ID="3", SHAPE="S", INDEX=2),
]
reg_list_single = [RegisterOperand(PREFIX_ID = "z", NAME_ID = "1", SHAPE = 'd')]
reg_list_single = [RegisterOperand(PREFIX_ID="z", NAME_ID="1", SHAPE="d")]
prange = self.parser.parse_line(instr_range)
plist = self.parser.parse_line(instr_list)
p_idx_range = self.parser.parse_line(instr_range_with_index)
p_idx_list = self.parser.parse_line(instr_list_with_index)
p_single = self.parser.parse_line(instr_range_single)
#print("\n",p_idx_list.operands,"\n")
#print("\n",reg_list_idx,"\n")
#self.assertEqual(prange.operands, reg_list)
self.assertEqual(prange.operands, reg_list)
self.assertEqual(plist.operands, reg_list)
#self.assertEqual(p_idx_range.operands, reg_list_idx)
#self.assertEqual(p_idx_list.operands, reg_list_idx)
self.assertEqual(p_single.operands, reg_list_single)
self.assertEqual(p_idx_range.operands, reg_list_idx)
self.assertEqual(p_idx_list.operands, reg_list_idx)
# self.assertEqual(p_single.operands, reg_list_single)
def test_reg_dependency(self):
reg_1_1 = {"prefix": "b", "name": "1"}
@@ -434,17 +449,23 @@ class TestParserAArch64(unittest.TestCase):
##################
def _get_comment(self, parser, comment):
return " ".join(
parser.process_operand(parser.comment.parseString(comment, parseAll=True).asDict())['comment']
parser.process_operand(parser.comment.parseString(comment, parseAll=True).asDict())[
"comment"
]
)
def _get_label(self, parser, label):
return parser.process_operand(parser.label.parseString(label, parseAll=True).asDict())
def _get_directive(self, parser, directive):
return parser.process_operand(parser.directive.parseString(directive, parseAll=True).asDict())
return parser.process_operand(
parser.directive.parseString(directive, parseAll=True).asDict()
)
def _get_condition(self, parser, condition):
return parser.process_operand(parser.condition.parseString(condition, parseAll=True).asDict())['condition']
return parser.process_operand(
parser.condition.parseString(condition, parseAll=True).asDict()
)["condition"]
@staticmethod
def _find_file(name):

View File

@@ -11,6 +11,7 @@ from pyparsing import ParseException
from osaca.parser import ParserX86ATT, InstructionForm
from osaca.parser.register import RegisterOperand
class TestParserX86ATT(unittest.TestCase):
@classmethod
def setUpClass(self):
@@ -86,12 +87,16 @@ class TestParserX86ATT(unittest.TestCase):
"byte",
)
self.assertEqual(
self._get_directive(self.parser, " .byte 100,103,144 #IACA START").parameters[2],
self._get_directive(
self.parser, " .byte 100,103,144 #IACA START"
).parameters[2],
"144",
)
self.assertEqual(
" ".join(
self._get_directive(self.parser, " .byte 100,103,144 #IACA START").comment
self._get_directive(
self.parser, " .byte 100,103,144 #IACA START"
).comment
),
"IACA START",
)
@@ -119,24 +124,24 @@ class TestParserX86ATT(unittest.TestCase):
self.assertEqual(parsed_1.comment, "12.27")
self.assertEqual(parsed_2.instruction, "jb")
self.assertEqual(parsed_2.operands[0]['identifier']['name'], "..B1.4")
self.assertEqual(parsed_2.operands[0]["identifier"]["name"], "..B1.4")
self.assertEqual(len(parsed_2.operands), 1)
self.assertIsNone(parsed_2.comment)
self.assertEqual(parsed_3.instruction, "movl")
self.assertEqual(parsed_3.operands[0]['value'], 222)
self.assertEqual(parsed_3.operands[0]["value"], 222)
self.assertEqual(parsed_3.operands[1].name, "ebx")
self.assertEqual(parsed_3.comment, "IACA END")
self.assertEqual(parsed_4.instruction, "vmovss")
self.assertEqual(parsed_4.operands[1].offset['value'], -4)
self.assertEqual(parsed_4.operands[1].base['name'], "rsp")
self.assertEqual(parsed_4.operands[1].index['name'], "rax")
self.assertEqual(parsed_4.operands[1].offset["value"], -4)
self.assertEqual(parsed_4.operands[1].base["name"], "rsp")
self.assertEqual(parsed_4.operands[1].index["name"], "rax")
self.assertEqual(parsed_4.operands[1].scale, 8)
self.assertEqual(parsed_4.operands[0].name, "xmm4")
self.assertEqual(parsed_4.comment, "12.9")
self.assertEqual(parsed_5.instruction, "mov")
self.assertEqual(parsed_5.operands[1].offset['identifier']['name'], "var")
self.assertEqual(parsed_5.operands[1].offset["identifier"]["name"], "var")
self.assertIsNone(parsed_5.operands[1].base)
self.assertIsNone(parsed_5.operands[1].index)
self.assertEqual(parsed_5.operands[1].scale, 1)
@@ -145,11 +150,11 @@ class TestParserX86ATT(unittest.TestCase):
self.assertEqual(parsed_6.instruction, "lea")
self.assertIsNone(parsed_6.operands[0].offset)
self.assertIsNone(parsed_6.operands[0].base)
self.assertEqual(parsed_6.operands[0].index['name'], "rax")
self.assertEqual(parsed_6.operands[0].index["name"], "rax")
self.assertEqual(parsed_6.operands[0].scale, 8)
self.assertEqual(parsed_6.operands[1].name, "rbx")
self.assertEqual(parsed_7.operands[0]['value'], 0x1)
self.assertEqual(parsed_7.operands[0]["value"], 0x1)
self.assertEqual(parsed_7.operands[1].name, "xmm0")
self.assertEqual(parsed_7.operands[2].name, "ymm1")
self.assertEqual(parsed_7.operands[3].name, "ymm1")
@@ -304,14 +309,18 @@ class TestParserX86ATT(unittest.TestCase):
##################
def _get_comment(self, parser, comment):
return " ".join(
parser.process_operand(parser.comment.parseString(comment, parseAll=True).asDict())['comment']
parser.process_operand(parser.comment.parseString(comment, parseAll=True).asDict())[
"comment"
]
)
def _get_label(self, parser, label):
return parser.process_operand(parser.label.parseString(label, parseAll=True).asDict())
def _get_directive(self, parser, directive):
return parser.process_operand(parser.directive.parseString(directive, parseAll=True).asDict())
return parser.process_operand(
parser.directive.parseString(directive, parseAll=True).asDict()
)
@staticmethod
def _find_file(name):