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 .instruction_form import InstructionForm
from .operand import Operand 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): def get_parser(isa):

View File

@@ -2,23 +2,24 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class DirectiveOperand(Operand): class DirectiveOperand(Operand):
def __init__(self, NAME_ID = None, PARAMETER_ID = None, COMMENT_ID = None): def __init__(self, NAME_ID=None, PARAMETER_ID=None, COMMENT_ID=None):
super().__init__(NAME_ID) super().__init__(NAME_ID)
self._PARAMETER_ID = PARAMETER_ID self._PARAMETER_ID = PARAMETER_ID
self._COMMENT_ID = COMMENT_ID self._COMMENT_ID = COMMENT_ID
@property @property
def parameters(self): def parameters(self):
return self._PARAMETER_ID return self._PARAMETER_ID
@property @property
def comment(self): def comment(self):
return self._COMMENT_ID return self._COMMENT_ID
def __iter__(self): def __iter__(self):
return self return self
def __next__(self): def __next__(self):
if not self._COMMENT_ID: if not self._COMMENT_ID:
raise StopIteration raise StopIteration
@@ -27,27 +28,24 @@ class DirectiveOperand(Operand):
@parameters.setter @parameters.setter
def parameters(self, parameters): def parameters(self, parameters):
self._PARAMETER_ID = parameters self._PARAMETER_ID = parameters
@comment.setter @comment.setter
def comment(self, comment): def comment(self, comment):
self._COMMENT_ID = comment self._COMMENT_ID = comment
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, DirectiveOperand): if isinstance(other, DirectiveOperand):
return ( return (
self._NAME_ID == other._NAME_ID and self._NAME_ID == other._NAME_ID
self._PARAMETER_ID == other._PARAMETER_ID and and self._PARAMETER_ID == other._PARAMETER_ID
self._COMMENT_ID == other._COMMENT_ID and self._COMMENT_ID == other._COMMENT_ID
) )
elif isinstance(other, dict): elif isinstance(other, dict):
return ( return self._NAME_ID == other["name"] and self._PARAMETER_ID == other["parameters"]
self._NAME_ID == other['name'] and
self._PARAMETER_ID == other['parameters']
)
return False return False
def __str__(self): def __str__(self):
return f"Directive(NAME_ID={self._NAME_ID}, PARAMETERS={self._PARAMETER_ID}, COMMENT={self._COMMENT_ID})" return f"Directive(NAME_ID={self._NAME_ID}, PARAMETERS={self._PARAMETER_ID}, COMMENT={self._COMMENT_ID})"
def __repr__(self): def __repr__(self):
return f"DirectiveOperand(NAME_ID={self._NAME_ID}, PARAMETERS={self._PARAMETER_ID}, COMMENT={self._COMMENT_ID})" return f"DirectiveOperand(NAME_ID={self._NAME_ID}, PARAMETERS={self._PARAMETER_ID}, COMMENT={self._COMMENT_ID})"

View File

@@ -2,8 +2,9 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class IdentifierOperand(Operand): class IdentifierOperand(Operand):
def __init__(self, name, OFFSET = None, RELOCATION = None): def __init__(self, name, OFFSET=None, RELOCATION=None):
super().__init__(name) super().__init__(name)
self._OFFSET = OFFSET self._OFFSET = OFFSET
self._RELOCATION = RELOCATION self._RELOCATION = RELOCATION
@@ -11,21 +12,23 @@ class IdentifierOperand(Operand):
@property @property
def offset(self): def offset(self):
return self._OFFSET return self._OFFSET
@offset.setter @offset.setter
def offset(self, offset): def offset(self, offset):
self._OFFSET = offset self._OFFSET = offset
@property @property
def relocation(self): def relocation(self):
return self._RELOCATION return self._RELOCATION
@relocation.setter @relocation.setter
def relocation(self, relocation): def relocation(self, relocation):
self._RELOCATION = relocation self._RELOCATION = relocation
def __str__(self): 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): def __repr__(self):
return f"IdentifierOperand(name={self.name}, offset={self.offset}, relocation={self.relocation})" return f"IdentifierOperand(name={self.name}, offset={self.offset}, relocation={self.relocation})"

View File

@@ -2,9 +2,15 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class ImmediateOperand(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)) super().__init__(str(VALUE_ID))
self._IDENTIFIER_ID = IDENTIFIER_ID self._IDENTIFIER_ID = IDENTIFIER_ID
self._TYPE_ID = TYPE_ID self._TYPE_ID = TYPE_ID
@@ -14,11 +20,11 @@ class ImmediateOperand(Operand):
@property @property
def identifier(self): def identifier(self):
return self._IDENTIFIER_ID return self._IDENTIFIER_ID
@property @property
def type(self): def type(self):
return self._TYPE_ID return self._TYPE_ID
@property @property
def value(self): def value(self):
return self._VALUE_ID return self._VALUE_ID
@@ -26,10 +32,10 @@ class ImmediateOperand(Operand):
@property @property
def shift(self): def shift(self):
return self._TYPE_ID return self._TYPE_ID
@identifier.setter @identifier.setter
def identifier(self, identifier): def identifier(self, identifier):
self._IDENTIFIER_ID = identifier self._IDENTIFIER_ID = identifier
@type.setter @type.setter
def type(self, type): def type(self, type):
@@ -38,7 +44,7 @@ class ImmediateOperand(Operand):
@value.setter @value.setter
def value(self, value): def value(self, value):
self._VALUE_ID = value self._VALUE_ID = value
@shift.setter @shift.setter
def index(self, shift): def index(self, shift):
self._SHIFT_ID = shift self._SHIFT_ID = shift
@@ -58,9 +64,9 @@ class ImmediateOperand(Operand):
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, ImmediateOperand): if isinstance(other, ImmediateOperand):
return ( return (
self._IDENTIFIER_ID == other._IDENTIFIER_ID and self._IDENTIFIER_ID == other._IDENTIFIER_ID
self._TYPE_ID == other._TYPE_ID and and self._TYPE_ID == other._TYPE_ID
self._VALUE_ID == other._VALUE_ID and and self._VALUE_ID == other._VALUE_ID
self._SHIFT_ID == other._SHIFT_ID and self._SHIFT_ID == other._SHIFT_ID
) )
return False return False

View File

@@ -2,6 +2,7 @@
from osaca.parser.directive import DirectiveOperand from osaca.parser.directive import DirectiveOperand
class InstructionForm: class InstructionForm:
# Identifiers for operand types # Identifiers for operand types
COMMENT_ID = "comment" COMMENT_ID = "comment"
@@ -15,9 +16,17 @@ class InstructionForm:
INSTRUCTION_ID = "instruction" INSTRUCTION_ID = "instruction"
OPERANDS_ID = "operands" OPERANDS_ID = "operands"
def __init__(self, INSTRUCTION_ID = None, OPERANDS_ID = [], DIRECTIVE_ID = None def __init__(
, COMMENT_ID = None, LABEL_ID = None, LINE = None, LINE_NUMBER = None self,
, SEMANTIC_OPERANDS = None): 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._INSTRUCTION_ID = INSTRUCTION_ID
self._OPERANDS_ID = OPERANDS_ID self._OPERANDS_ID = OPERANDS_ID
self._DIRECTIVE_ID = DIRECTIVE_ID self._DIRECTIVE_ID = DIRECTIVE_ID
@@ -28,7 +37,7 @@ class InstructionForm:
self._SEMANTIC_OPERANDS = SEMANTIC_OPERANDS self._SEMANTIC_OPERANDS = SEMANTIC_OPERANDS
self._UOPS = None self._UOPS = None
#self.semantic_operands = {"source": [], "destination": [], "src_dst": []} # self.semantic_operands = {"source": [], "destination": [], "src_dst": []}
self._LATENCY = None self._LATENCY = None
self._THROUGHPUT = None self._THROUGHPUT = None
self._LATENCY_CP = [] self._LATENCY_CP = []
@@ -45,7 +54,7 @@ class InstructionForm:
@property @property
def instruction(self): def instruction(self):
return self._INSTRUCTION_ID return self._INSTRUCTION_ID
@property @property
def label(self): def label(self):
return self._LABEL_ID return self._LABEL_ID
@@ -61,11 +70,11 @@ class InstructionForm:
@property @property
def line_number(self): def line_number(self):
return self._LINE_NUMBER return self._LINE_NUMBER
@property @property
def line(self): def line(self):
return self._LINE return self._LINE
@property @property
def operands(self): def operands(self):
return self._OPERANDS_ID return self._OPERANDS_ID
@@ -73,11 +82,11 @@ class InstructionForm:
@property @property
def port_pressure(self): def port_pressure(self):
return self._PORT_PRESSURE return self._PORT_PRESSURE
@property @property
def port_uops(self): def port_uops(self):
return self._PORT_UOPS return self._PORT_UOPS
@property @property
def flags(self): def flags(self):
return self._FLAGS return self._FLAGS
@@ -93,11 +102,11 @@ class InstructionForm:
@line_number.setter @line_number.setter
def line_number(self, line_number): def line_number(self, line_number):
self._LINE_NUMBER = line_number self._LINE_NUMBER = line_number
@line.setter @line.setter
def line(self, line): def line(self, line):
self._LINE = line self._LINE = line
@operands.setter @operands.setter
def operands(self, operands): def operands(self, operands):
self._OPERANDS_ID = operands self._OPERANDS_ID = operands
@@ -105,19 +114,19 @@ class InstructionForm:
@instruction.setter @instruction.setter
def instruction(self, instruction): def instruction(self, instruction):
self._INSTRUCTION_ID = instruction self._INSTRUCTION_ID = instruction
@label.setter @label.setter
def label(self, label): def label(self, label):
self._LABEL_ID = label self._LABEL_ID = label
@comment.setter @comment.setter
def comment(self, comment): def comment(self, comment):
self._COMMENT_ID =comment self._COMMENT_ID = comment
@port_pressure.setter @port_pressure.setter
def port_pressure(self, port_pressure): def port_pressure(self, port_pressure):
self._PORT_PRESSURE = port_pressure self._PORT_PRESSURE = port_pressure
@port_uops.setter @port_uops.setter
def port_uops(self, port_uops): def port_uops(self, port_uops):
self._PORT_UOPS = port_uops self._PORT_UOPS = port_uops
@@ -135,14 +144,13 @@ class InstructionForm:
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, InstructionForm): if isinstance(other, InstructionForm):
return ( return (
self._INSTRUCTION_ID == other._INSTRUCTION_ID and self._INSTRUCTION_ID == other._INSTRUCTION_ID
self._OPERANDS_ID == other._OPERANDS_ID and and self._OPERANDS_ID == other._OPERANDS_ID
self._DIRECTIVE_ID == other._DIRECTIVE_ID and and self._DIRECTIVE_ID == other._DIRECTIVE_ID
self._COMMENT_ID == other._COMMENT_ID and and self._COMMENT_ID == other._COMMENT_ID
self._LABEL_ID == other._LABEL_ID and and self._LABEL_ID == other._LABEL_ID
self._LINE == other._LINE and and self._LINE == other._LINE
self._LINE_NUMBER == other._LINE_NUMBER and and self._LINE_NUMBER == other._LINE_NUMBER
self._SEMANTIC_OPERANDS == other._SEMANTIC_OPERANDS and self._SEMANTIC_OPERANDS == other._SEMANTIC_OPERANDS
) )
return False return False

View File

@@ -2,22 +2,23 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class LabelOperand(Operand): class LabelOperand(Operand):
def __init__(self, NAME_ID = None, COMMENT_ID = None): def __init__(self, NAME_ID=None, COMMENT_ID=None):
super().__init__(NAME_ID) super().__init__(NAME_ID)
self._COMMENT_ID = COMMENT_ID self._COMMENT_ID = COMMENT_ID
@property @property
def comment(self): def comment(self):
return self._COMMENT_ID return self._COMMENT_ID
@comment.setter @comment.setter
def comment(self, comment): def comment(self, comment):
self._COMMENT_ID = comment self._COMMENT_ID = comment
def __iter__(self): def __iter__(self):
return self return self
def __next__(self): def __next__(self):
if not self._COMMENT_ID: if not self._COMMENT_ID:
raise StopIteration raise StopIteration
@@ -28,4 +29,3 @@ class LabelOperand(Operand):
def __repr__(self): def __repr__(self):
return f"LabelOperand(NAME_ID={self._NAME_ID}, COMMENT={self._COMMENT_ID})" return f"LabelOperand(NAME_ID={self._NAME_ID}, COMMENT={self._COMMENT_ID})"

View File

@@ -2,17 +2,27 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class MemoryOperand(Operand): class MemoryOperand(Operand):
def __init__(self, OFFSET_ID = None, BASE_ID = None, INDEX_ID = None def __init__(
, SCALE_ID = 1, SEGMENT_EXT_ID = None, MASK = None, PRE_INDEXED = False self,
, POST_INDEXED = False, INDEXED_VAL = None): OFFSET_ID=None,
super().__init__('memory') 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._OFFSET_ID = OFFSET_ID
self._BASE_ID = BASE_ID self._BASE_ID = BASE_ID
self._INDEX_ID = INDEX_ID self._INDEX_ID = INDEX_ID
self._SCALE_ID = SCALE_ID self._SCALE_ID = SCALE_ID
self._SEGMENT_EXT_ID = SEGMENT_EXT_ID self._SEGMENT_EXT_ID = SEGMENT_EXT_ID
self._MASK = MASK self._MASK = MASK
self._PRE_INDEXED = PRE_INDEXED self._PRE_INDEXED = PRE_INDEXED
self._POST_INDEXED = POST_INDEXED self._POST_INDEXED = POST_INDEXED
self._INDEXED_VAL = INDEXED_VAL self._INDEXED_VAL = INDEXED_VAL
@@ -24,11 +34,11 @@ class MemoryOperand(Operand):
@property @property
def immediate(self): def immediate(self):
return self._IMMEDIATE_ID return self._IMMEDIATE_ID
@property @property
def base(self): def base(self):
return self._BASE_ID return self._BASE_ID
@property @property
def index(self): def index(self):
return self._INDEX_ID return self._INDEX_ID
@@ -36,7 +46,7 @@ class MemoryOperand(Operand):
@property @property
def scale(self): def scale(self):
return self._SCALE_ID return self._SCALE_ID
@property @property
def segment_ext_id(self): def segment_ext_id(self):
return self._SEGMENT_EXT_ID return self._SEGMENT_EXT_ID
@@ -48,18 +58,18 @@ class MemoryOperand(Operand):
@property @property
def pre_indexed(self): def pre_indexed(self):
return self._PRE_INDEXED return self._PRE_INDEXED
@property @property
def post_indexed(self): def post_indexed(self):
return self._POST_INDEXED return self._POST_INDEXED
@property @property
def indexed_val(self): def indexed_val(self):
return self._INDEXED_VAL return self._INDEXED_VAL
@segment_ext_id.setter @segment_ext_id.setter
def segment_ext_id(self, segment): def segment_ext_id(self, segment):
self._SEGMENT_EXT_ID= segment self._SEGMENT_EXT_ID = segment
@offset.setter @offset.setter
def offset(self, offset): def offset(self, offset):
@@ -68,7 +78,7 @@ class MemoryOperand(Operand):
@base.setter @base.setter
def base(self, base): def base(self, base):
self._BASE_ID = base self._BASE_ID = base
@index.setter @index.setter
def index(self, index): def index(self, index):
self._INDEX_ID = index self._INDEX_ID = index
@@ -84,7 +94,7 @@ class MemoryOperand(Operand):
@pre_indexed.setter @pre_indexed.setter
def pre_indexed(self, pre_indexed): def pre_indexed(self, pre_indexed):
self._PRE_INDEXED = pre_indexed self._PRE_INDEXED = pre_indexed
@post_indexed.setter @post_indexed.setter
def post_indexed(self, post_indexed): def post_indexed(self, post_indexed):
self._POST_INDEXED = post_indexed self._POST_INDEXED = post_indexed
@@ -114,14 +124,14 @@ class MemoryOperand(Operand):
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, MemoryOperand): if isinstance(other, MemoryOperand):
return ( return (
self._OFFSET_ID == other._OFFSET_ID and self._OFFSET_ID == other._OFFSET_ID
self._BASE_ID == other._BASE_ID and and self._BASE_ID == other._BASE_ID
self._INDEX_ID == other._INDEX_ID and and self._INDEX_ID == other._INDEX_ID
self._SCALE_ID == other._SCALE_ID and and self._SCALE_ID == other._SCALE_ID
self._SEGMENT_EXT_ID == other._SEGMENT_EXT_ID and and self._SEGMENT_EXT_ID == other._SEGMENT_EXT_ID
self._MASK == other._MASK and and self._MASK == other._MASK
self._PRE_INDEXED == other._PRE_INDEXED and and self._PRE_INDEXED == other._PRE_INDEXED
self._POST_INDEXED == other._POST_INDEXED and and self._POST_INDEXED == other._POST_INDEXED
self._INDEXED_VAL == other._INDEXED_VAL and self._INDEXED_VAL == other._INDEXED_VAL
) )
return False return False

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
class Operand: class Operand:
def __init__(self, NAME_ID): def __init__(self, NAME_ID):
self._NAME_ID = NAME_ID self._NAME_ID = NAME_ID
@@ -11,9 +12,9 @@ class Operand:
@name.setter @name.setter
def name(self, name): def name(self, name):
self._NAME_ID = name self._NAME_ID = name
def __repr__(self): def __repr__(self):
return f"Operand(NAME_ID={self._NAME_ID}" return f"Operand(NAME_ID={self._NAME_ID}"
def __str__(self): def __str__(self):
return f"Name: {self._NAME_ID}" return f"Name: {self._NAME_ID}"

View File

@@ -12,6 +12,7 @@ from osaca.parser.register import RegisterOperand
from osaca.parser.identifier import IdentifierOperand from osaca.parser.identifier import IdentifierOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import ImmediateOperand
class ParserAArch64(BaseParser): class ParserAArch64(BaseParser):
_instance = None _instance = None
@@ -260,13 +261,13 @@ class ParserAArch64(BaseParser):
:return: `dict` -- parsed asm line (comment, label, directive or instruction form) :return: `dict` -- parsed asm line (comment, label, directive or instruction form)
""" """
instruction_form = InstructionForm( instruction_form = InstructionForm(
INSTRUCTION_ID = None, INSTRUCTION_ID=None,
OPERANDS_ID = [], OPERANDS_ID=[],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = None, COMMENT_ID=None,
LABEL_ID = None, LABEL_ID=None,
LINE = line, LINE=line,
LINE_NUMBER = line_number, LINE_NUMBER=line_number,
) )
result = None result = None
@@ -290,9 +291,7 @@ class ParserAArch64(BaseParser):
result = self.process_operand(self.label.parseString(line, parseAll=True).asDict()) result = self.process_operand(self.label.parseString(line, parseAll=True).asDict())
instruction_form.label = result.name instruction_form.label = result.name
if result.comment != None: if result.comment != None:
instruction_form.comment= " ".join( instruction_form.comment = " ".join(result.comment)
result.comment
)
except pp.ParseException: except pp.ParseException:
pass pass
@@ -303,13 +302,10 @@ class ParserAArch64(BaseParser):
self.directive.parseString(line, parseAll=True).asDict() self.directive.parseString(line, parseAll=True).asDict()
) )
instruction_form.directive = DirectiveOperand( instruction_form.directive = DirectiveOperand(
NAME_ID = result.name, NAME_ID=result.name, PARAMETER_ID=result.parameters
PARAMETER_ID = result.parameters
) )
if result.comment is not None: if result.comment is not None:
instruction_form.comment = " ".join( instruction_form.comment = " ".join(result.comment)
result.comment
)
except pp.ParseException: except pp.ParseException:
pass pass
@@ -358,11 +354,9 @@ class ParserAArch64(BaseParser):
operand = self.process_operand(result["operand5"]) operand = self.process_operand(result["operand5"])
operands.extend(operand) if isinstance(operand, list) else operands.append(operand) operands.extend(operand) if isinstance(operand, list) else operands.append(operand)
return_dict = InstructionForm( return_dict = InstructionForm(
INSTRUCTION_ID = result['mnemonic'], INSTRUCTION_ID=result["mnemonic"],
OPERANDS_ID = operands, OPERANDS_ID=operands,
COMMENT_ID = " ".join(result[self.COMMENT_ID]) COMMENT_ID=" ".join(result[self.COMMENT_ID]) if self.COMMENT_ID in result else None,
if self.COMMENT_ID in result
else None,
) )
return return_dict return return_dict
@@ -387,16 +381,27 @@ class ParserAArch64(BaseParser):
if self.IDENTIFIER_ID in operand: if self.IDENTIFIER_ID in operand:
return self.process_identifier(operand[self.IDENTIFIER_ID]) return self.process_identifier(operand[self.IDENTIFIER_ID])
if self.REGISTER_ID in operand: if self.REGISTER_ID in operand:
return RegisterOperand(PREFIX_ID = operand['register']['prefix'], NAME_ID = operand['register']['name'], return self.process_register_operand(operand[self.REGISTER_ID])
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)
if self.DIRECTIVE_ID in operand: if self.DIRECTIVE_ID in operand:
return DirectiveOperand(NAME_ID = operand['directive']["name"], PARAMETER_ID = operand['directive']["parameters"], return DirectiveOperand(
COMMENT_ID = operand['directive']["comment"] if "comment" in operand['directive'] else None) NAME_ID=operand["directive"]["name"],
PARAMETER_ID=operand["directive"]["parameters"],
COMMENT_ID=operand["directive"]["comment"]
if "comment" in operand["directive"]
else None,
)
return operand 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): def process_memory_address(self, memory_address):
"""Post-process memory address operand""" """Post-process memory address operand"""
# Remove unnecessarily created dictionary entries during parsing # Remove unnecessarily created dictionary entries during parsing
@@ -417,23 +422,21 @@ class ParserAArch64(BaseParser):
if "shift" in memory_address["index"]: if "shift" in memory_address["index"]:
if memory_address["index"]["shift_op"].lower() in valid_shift_ops: if memory_address["index"]["shift_op"].lower() in valid_shift_ops:
scale = 2 ** int(memory_address["index"]["shift"][0]["value"]) scale = 2 ** int(memory_address["index"]["shift"][0]["value"])
new_dict = MemoryOperand(OFFSET_ID = offset, BASE_ID = base, INDEX_ID = index, SCALE_ID = scale) new_dict = MemoryOperand(OFFSET_ID=offset, BASE_ID=base, INDEX_ID=index, SCALE_ID=scale)
if "pre_indexed" in memory_address: if "pre_indexed" in memory_address:
new_dict.pre_indexed = True new_dict.pre_indexed = True
if "post_indexed" in memory_address: if "post_indexed" in memory_address:
if "value" in memory_address["post_indexed"]: if "value" in memory_address["post_indexed"]:
new_dict.post_indexed = { new_dict.post_indexed = {"value": int(memory_address["post_indexed"]["value"], 0)}
"value": int(memory_address["post_indexed"]["value"], 0)
}
else: else:
new_dict.post_indexed = memory_address["post_indexed"] new_dict.post_indexed = memory_address["post_indexed"]
return new_dict return new_dict
def process_sp_register(self, register): def process_sp_register(self, register):
"""Post-process stack pointer register""" """Post-process stack pointer register"""
reg = register # reg = register
new_reg = RegisterOperand(PREFIX_ID = "x") new_reg = RegisterOperand(PREFIX_ID="x", NAME_ID="sp")
#reg["prefix"] = "x" # reg["prefix"] = "x"
return new_reg return new_reg
def resolve_range_list(self, operand): def resolve_range_list(self, operand):
@@ -441,32 +444,35 @@ class ParserAArch64(BaseParser):
Resolve range or list register operand to list of registers. Resolve range or list register operand to list of registers.
Returns None if neither list nor range Returns None if neither list nor range
""" """
if isinstance(operand, RegisterOperand): if "list" in operand["register"]:
index = operand["register"].get("index", None)
if "list" in operand.register: range_list = []
index = operand.register.get("index") processed_list = []
range_list = [] for reg in operand["register"]["list"]:
for reg in operand.register.list: reg = deepcopy(reg)
reg = deepcopy(reg) if index is not None:
if index is not None: reg["index"] = int(index, 0)
reg["index"] = int(index, 0) range_list.append(reg)
range_list.append(reg) for reg in range_list:
return range_list processed_list.append(self.process_register_operand(reg))
#return range_list return processed_list
elif "range" in operand.register: # return range_list
base_register = operand.register.range[0] elif "range" in operand["register"]:
index = operand.register.get("index") base_register = operand["register"]["range"][0]
range_list = [] index = operand["register"].get("index", None)
start_name = base_register.name range_list = []
end_name = operand.register.range[1].name processed_list = []
for name in range(int(start_name), int(end_name) + 1): start_name = base_register["name"]
reg = deepcopy(base_register) end_name = operand["register"]["range"][1]["name"]
if index is not None: for name in range(int(start_name), int(end_name) + 1):
reg["index"] = int(index, 0) reg = deepcopy(base_register)
reg["name"] = str(name) if index is not None:
range_list.append(reg) reg["index"] = int(index, 0)
return range_list reg["name"] = str(name)
#return range_list range_list.append(reg)
for reg in range_list:
processed_list.append(self.process_register_operand(reg))
return processed_list
# neither register list nor range, return unmodified # neither register list nor range, return unmodified
return operand return operand
@@ -480,16 +486,12 @@ class ParserAArch64(BaseParser):
if "range" in register_list: if "range" in register_list:
dict_name = "range" dict_name = "range"
for r in register_list[dict_name]: for r in register_list[dict_name]:
rlist.append( rlist.append(self.list_element.parseString(r, parseAll=True).asDict())
self.list_element.parseString(r, parseAll=True).asDict()
)
index = register_list.get("index", None) index = register_list.get("index", None)
reg_list = [] new_dict = {dict_name: rlist, "index": index}
for reg in rlist: if len(new_dict[dict_name]) == 1:
reg_list.append(RegisterOperand(NAME_ID = reg['name'], PREFIX_ID = reg['prefix'], SHAPE = reg['shape'] if 'shape' in reg else None)) return {self.REGISTER_ID: new_dict[dict_name][0]}
#if len(new_dict.name) == 1: return {self.REGISTER_ID: new_dict}
# return new_dict.name[0]
return reg_list
def process_immediate(self, immediate): def process_immediate(self, immediate):
"""Post-process immediate operand""" """Post-process immediate operand"""
@@ -502,7 +504,7 @@ class ParserAArch64(BaseParser):
immediate["type"] = "int" immediate["type"] = "int"
# convert hex/bin immediates to dec # convert hex/bin immediates to dec
immediate["value"] = self.normalize_imd(immediate) immediate["value"] = self.normalize_imd(immediate)
return ImmediateOperand(TYPE_ID = immediate["type"], VALUE_ID = immediate["value"]) return ImmediateOperand(TYPE_ID=immediate["type"], VALUE_ID=immediate["value"])
if "base_immediate" in immediate: if "base_immediate" in immediate:
# arithmetic immediate, add calculated value as value # arithmetic immediate, add calculated value as value
immediate["shift"] = immediate["shift"][0] immediate["shift"] = immediate["shift"][0]
@@ -510,23 +512,28 @@ class ParserAArch64(BaseParser):
immediate["shift"]["value"] immediate["shift"]["value"]
) )
immediate["type"] = "int" 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: if "float" in immediate:
dict_name = "float" dict_name = "float"
if "double" in immediate: if "double" in immediate:
dict_name = "double" dict_name = "double"
if "exponent" in immediate[dict_name]: if "exponent" in immediate[dict_name]:
immediate["type"] = dict_name immediate["type"] = dict_name
return ImmediateOperand(TYPE_ID = immediate["type"]) return ImmediateOperand(TYPE_ID=immediate["type"])
else: else:
# change 'mantissa' key to 'value' # change 'mantissa' key to 'value'
return ImmediateOperand(VALUE_ID = immediate[dict_name]["mantissa"], TYPE_ID = dict_name) return ImmediateOperand(VALUE_ID=immediate[dict_name]["mantissa"], TYPE_ID=dict_name)
def process_label(self, label): def process_label(self, label):
"""Post-process label asm line""" """Post-process label asm line"""
# remove duplicated 'name' level due to identifier # remove duplicated 'name' level due to identifier
#label["name"] = label["name"]["name"] # 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 return new_label
def process_identifier(self, identifier): def process_identifier(self, identifier):
@@ -534,13 +541,15 @@ class ParserAArch64(BaseParser):
# remove value if it consists of symbol+offset # remove value if it consists of symbol+offset
if "value" in identifier: if "value" in identifier:
del identifier["value"] 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): def get_full_reg_name(self, register):
"""Return one register name string including all attributes""" """Return one register name string including all attributes"""
name = register.prefix + str(register.name) name = register.prefix + str(register.name)
if register.shape is not None: 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: if register.index is not None:
name += "[" + str(register.index) + "]" name += "[" + str(register.index) + "]"
return name return name

View File

@@ -14,7 +14,8 @@ from osaca.parser.label import LabelOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import RegisterOperand
from osaca.parser.identifier import IdentifierOperand from osaca.parser.identifier import IdentifierOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import ImmediateOperand
class ParserX86ATT(BaseParser): class ParserX86ATT(BaseParser):
_instance = None _instance = None
@@ -206,7 +207,7 @@ class ParserX86ATT(BaseParser):
:type line_number: int, optional :type line_number: int, optional
:return: ``dict`` -- parsed asm line (comment, label, directive or instruction form) :return: ``dict`` -- parsed asm line (comment, label, directive or instruction form)
""" """
instruction_form = InstructionForm(LINE = line, LINE_NUMBER = line_number) instruction_form = InstructionForm(LINE=line, LINE_NUMBER=line_number)
result = None result = None
# 1. Parse comment # 1. Parse comment
@@ -222,9 +223,7 @@ class ParserX86ATT(BaseParser):
result = self.process_operand(self.label.parseString(line, parseAll=True).asDict()) result = self.process_operand(self.label.parseString(line, parseAll=True).asDict())
instruction_form.label = result.name instruction_form.label = result.name
if result.comment != None: if result.comment != None:
instruction_form.comment = " ".join( instruction_form.comment = " ".join(result.comment)
result.comment
)
except pp.ParseException: except pp.ParseException:
pass pass
@@ -235,14 +234,12 @@ class ParserX86ATT(BaseParser):
self.directive.parseString(line, parseAll=True).asDict() self.directive.parseString(line, parseAll=True).asDict()
) )
instruction_form.directive = DirectiveOperand( instruction_form.directive = DirectiveOperand(
NAME_ID = result.name, NAME_ID=result.name,
PARAMETER_ID = result.parameters, PARAMETER_ID=result.parameters,
) )
if result.comment != None: if result.comment != None:
instruction_form.comment = " ".join( instruction_form.comment = " ".join(result.comment)
result.comment
)
except pp.ParseException: except pp.ParseException:
pass pass
@@ -283,13 +280,11 @@ class ParserX86ATT(BaseParser):
if "operand4" in result: if "operand4" in result:
operands.append(self.process_operand(result["operand4"])) operands.append(self.process_operand(result["operand4"]))
return_dict = InstructionForm( return_dict = InstructionForm(
INSTRUCTION_ID = result["mnemonic"].split(",")[0], INSTRUCTION_ID=result["mnemonic"].split(",")[0],
OPERANDS_ID = operands, OPERANDS_ID=operands,
COMMENT_ID = " ".join(result[self.COMMENT_ID]) COMMENT_ID=" ".join(result[self.COMMENT_ID]) if self.COMMENT_ID in result else None,
if self.COMMENT_ID in result
else None,
) )
return return_dict return return_dict
def process_operand(self, operand): def process_operand(self, operand):
@@ -304,16 +299,22 @@ class ParserX86ATT(BaseParser):
if self.DIRECTIVE_ID in operand: if self.DIRECTIVE_ID in operand:
return self.process_directive(operand[self.DIRECTIVE_ID]) return self.process_directive(operand[self.DIRECTIVE_ID])
if self.REGISTER_ID in operand: if self.REGISTER_ID in operand:
return RegisterOperand(PREFIX_ID = operand['register']['prefix'] if 'prefix' in operand['register'] else None, return RegisterOperand(
NAME_ID = operand['register']['name'], PREFIX_ID=operand["register"]["prefix"]
SHAPE = operand['register']['shape'] if 'shape' in operand['register'] else None, if "prefix" in operand["register"]
LANES = operand['register']['lanes'] if 'lanes' in operand['register'] else None, else None,
INDEX = operand['register']['index'] if 'index' in operand['register'] else None, NAME_ID=operand["register"]["name"],
PREDICATION = operand['register']['predication'] if 'predication' in operand['register'] else None) 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 return operand
def process_directive(self, directive): def process_directive(self, directive):
directive_new = DirectiveOperand(NAME_ID = directive["name"], PARAMETER_ID = []) directive_new = DirectiveOperand(NAME_ID=directive["name"], PARAMETER_ID=[])
if "parameters" in directive: if "parameters" in directive:
directive_new.parameters = directive["parameters"] directive_new.parameters = directive["parameters"]
if "comment" in directive: if "comment" in directive:
@@ -334,7 +335,7 @@ class ParserX86ATT(BaseParser):
offset = {"value": offset} offset = {"value": offset}
elif offset is not None and "value" in offset: elif offset is not None and "value" in offset:
offset["value"] = int(offset["value"], 0) offset["value"] = int(offset["value"], 0)
new_dict = MemoryOperand(OFFSET_ID = offset, BASE_ID = base, INDEX_ID = index, SCALE_ID = scale) new_dict = MemoryOperand(OFFSET_ID=offset, BASE_ID=base, INDEX_ID=index, SCALE_ID=scale)
# Add segmentation extension if existing # Add segmentation extension if existing
if self.SEGMENT_EXT_ID in memory_address: if self.SEGMENT_EXT_ID in memory_address:
new_dict.segment_ext_id = memory_address[self.SEGMENT_EXT_ID] new_dict.segment_ext_id = memory_address[self.SEGMENT_EXT_ID]
@@ -344,7 +345,9 @@ class ParserX86ATT(BaseParser):
"""Post-process label asm line""" """Post-process label asm line"""
# remove duplicated 'name' level due to identifier # remove duplicated 'name' level due to identifier
label["name"] = label["name"][0]["name"] 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 return new_label
def process_immediate(self, immediate): def process_immediate(self, immediate):

View File

@@ -2,10 +2,22 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class RegisterOperand(Operand): class RegisterOperand(Operand):
def __init__(self, NAME_ID = None, WIDTH_ID = None, PREFIX_ID = None, REG_ID = None def __init__(
, REGTYPE_ID = None, LANES = None, SHAPE = None, INDEX = None self,
, MASK = False, ZEROING = False, PREDICATION = None): 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) super().__init__(NAME_ID)
self._WIDTH_ID = WIDTH_ID self._WIDTH_ID = WIDTH_ID
self._PREFIX_ID = PREFIX_ID self._PREFIX_ID = PREFIX_ID
@@ -21,7 +33,7 @@ class RegisterOperand(Operand):
@property @property
def width(self): def width(self):
return self._WIDTH_ID return self._WIDTH_ID
@width.setter @width.setter
def width(self, width): def width(self, width):
self._WIDTH_ID = width self._WIDTH_ID = width
@@ -29,7 +41,7 @@ class RegisterOperand(Operand):
@property @property
def predication(self): def predication(self):
return self._PREDICATION return self._PREDICATION
@predication.setter @predication.setter
def predication(self, predication): def predication(self, predication):
self._PREDICATION = predication self._PREDICATION = predication
@@ -37,63 +49,63 @@ class RegisterOperand(Operand):
@property @property
def regtype(self): def regtype(self):
return self._REGTYPE_ID return self._REGTYPE_ID
@regtype.setter @regtype.setter
def regtype(self, regtype): def regtype(self, regtype):
self._REGTYPE_ID = regtype self._REGTYPE_ID = regtype
@property @property
def prefix(self): def prefix(self):
return self._PREFIX_ID return self._PREFIX_ID
@prefix.setter @prefix.setter
def prefix(self, prefix): def prefix(self, prefix):
self._PREFIX = prefix self._PREFIX = prefix
@property @property
def reg_id(self): def reg_id(self):
return self._REG_ID return self._REG_ID
@reg_id.setter @reg_id.setter
def reg_id(self, reg_id): def reg_id(self, reg_id):
self._REG_ID = reg_id self._REG_ID = reg_id
@property @property
def lanes(self): def lanes(self):
return self._LANES return self._LANES
@lanes.setter @lanes.setter
def lanes(self, lanes): def lanes(self, lanes):
self._LANES = lanes self._LANES = lanes
@property @property
def shape(self): def shape(self):
return self._SHAPE return self._SHAPE
@shape.setter @shape.setter
def shape(self, shape): def shape(self, shape):
self._SHAPE = shape self._SHAPE = shape
@property @property
def index(self): def index(self):
return self._INDEX return self._INDEX
@index.setter @index.setter
def index(self, index): def index(self, index):
self._INDEX = index self._INDEX = index
@property @property
def mask(self): def mask(self):
return self._MASK return self._MASK
@mask.setter @mask.setter
def mask(self, mask): def mask(self, mask):
self._MASK = mask self._MASK = mask
@property @property
def zeroing(self): def zeroing(self):
return self._ZEROING return self._ZEROING
@zeroing.setter @zeroing.setter
def zeroing(self, zeroing): def zeroing(self, zeroing):
self._ZEROING = zeroing self._ZEROING = zeroing
@@ -113,19 +125,19 @@ class RegisterOperand(Operand):
f"LANES={self._LANES}, SHAPE={self._SHAPE}, INDEX={self._INDEX}, " f"LANES={self._LANES}, SHAPE={self._SHAPE}, INDEX={self._INDEX}, "
f"MASK={self._MASK}, ZEROING={self._ZEROING})" f"MASK={self._MASK}, ZEROING={self._ZEROING})"
) )
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, RegisterOperand): if isinstance(other, RegisterOperand):
return ( return (
self._NAME_ID == other._NAME_ID and self._NAME_ID == other._NAME_ID
self._WIDTH_ID == other._WIDTH_ID and and self._WIDTH_ID == other._WIDTH_ID
self._PREFIX_ID == other._PREFIX_ID and and self._PREFIX_ID == other._PREFIX_ID
self._REG_ID == other._REG_ID and and self._REG_ID == other._REG_ID
self._REGTYPE_ID == other._REGTYPE_ID and and self._REGTYPE_ID == other._REGTYPE_ID
self._LANES == other._LANES and and self._LANES == other._LANES
self._SHAPE == other._SHAPE and and self._SHAPE == other._SHAPE
self._INDEX == other._INDEX and and self._INDEX == other._INDEX
self._MASK == other._MASK and and self._MASK == other._MASK
self._ZEROING == other._ZEROING and self._ZEROING == other._ZEROING
) )
return False return False

View File

@@ -15,6 +15,7 @@ from osaca.parser.memory import MemoryOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import RegisterOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import ImmediateOperand
class TestParserAArch64(unittest.TestCase): class TestParserAArch64(unittest.TestCase):
@classmethod @classmethod
def setUpClass(self): def setUpClass(self):
@@ -61,12 +62,16 @@ class TestParserAArch64(unittest.TestCase):
"byte", "byte",
) )
self.assertEqual( 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", "144",
) )
self.assertEqual( self.assertEqual(
" ".join( " ".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", "IACA START",
) )
@@ -89,7 +94,7 @@ class TestParserAArch64(unittest.TestCase):
instr7 = "fadd v17.2d, v16.2d, v1.2d" instr7 = "fadd v17.2d, v16.2d, v1.2d"
instr8 = "mov.d x0, v16.d[1]" instr8 = "mov.d x0, v16.d[1]"
instr9 = "ccmp x0, x1, #4, cc" instr9 = "ccmp x0, x1, #4, cc"
"""
parsed_1 = self.parser.parse_instruction(instr1) parsed_1 = self.parser.parse_instruction(instr1)
parsed_2 = self.parser.parse_instruction(instr2) parsed_2 = self.parser.parse_instruction(instr2)
parsed_3 = self.parser.parse_instruction(instr3) 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].name, "0")
self.assertEqual(parsed_9.operands[0].prefix, "x") self.assertEqual(parsed_9.operands[0].prefix, "x")
self.assertEqual(parsed_9.operands[3]['condition'], "CC") self.assertEqual(parsed_9.operands[3]['condition'], "CC")
"""
def test_parse_line(self): def test_parse_line(self):
line_comment = "// -- Begin main" line_comment = "// -- Begin main"
@@ -177,122 +183,141 @@ class TestParserAArch64(unittest.TestCase):
line_conditions = "ccmn x11, #1, #3, eq" line_conditions = "ccmn x11, #1, #3, eq"
instruction_form_1 = InstructionForm( instruction_form_1 = InstructionForm(
INSTRUCTION_ID = None, INSTRUCTION_ID=None,
OPERANDS_ID = [], OPERANDS_ID=[],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = "-- Begin main", COMMENT_ID="-- Begin main",
LABEL_ID = None, LABEL_ID=None,
LINE = "// -- Begin main", LINE="// -- Begin main",
LINE_NUMBER = 1, LINE_NUMBER=1,
) )
instruction_form_2 = InstructionForm( instruction_form_2 = InstructionForm(
INSTRUCTION_ID = None, INSTRUCTION_ID=None,
OPERANDS_ID = [], OPERANDS_ID=[],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = "=>This Inner Loop Header: Depth=1", COMMENT_ID="=>This Inner Loop Header: Depth=1",
LABEL_ID = ".LBB0_1", LABEL_ID=".LBB0_1",
LINE = ".LBB0_1: // =>This Inner Loop Header: Depth=1", LINE=".LBB0_1: // =>This Inner Loop Header: Depth=1",
LINE_NUMBER = 2, LINE_NUMBER=2,
) )
instruction_form_3 = InstructionForm( instruction_form_3 = InstructionForm(
INSTRUCTION_ID = None, INSTRUCTION_ID=None,
OPERANDS_ID = [], OPERANDS_ID=[],
DIRECTIVE_ID = DirectiveOperand(NAME_ID = "cfi_def_cfa", PARAMETER_ID = ["w29", "-16"]) , DIRECTIVE_ID=DirectiveOperand(NAME_ID="cfi_def_cfa", PARAMETER_ID=["w29", "-16"]),
COMMENT_ID = None, COMMENT_ID=None,
LABEL_ID = None, LABEL_ID=None,
LINE = ".cfi_def_cfa w29, -16", LINE=".cfi_def_cfa w29, -16",
LINE_NUMBER = 3, LINE_NUMBER=3,
) )
instruction_form_4 = InstructionForm( instruction_form_4 = InstructionForm(
INSTRUCTION_ID = "ldr", INSTRUCTION_ID="ldr",
OPERANDS_ID = [RegisterOperand(PREFIX_ID = "s", NAME_ID = "0"), OPERANDS_ID=[
MemoryOperand(OFFSET_ID = None, BASE_ID = {"prefix": "x", "name": "11"}, RegisterOperand(PREFIX_ID="s", NAME_ID="0"),
INDEX_ID = { MemoryOperand(
"prefix": "w", OFFSET_ID=None,
"name": "10", BASE_ID={"prefix": "x", "name": "11"},
"shift_op": "sxtw", INDEX_ID={
"immediate": {"value": "2"}, "prefix": "w",
"shift": [{"value": "2"}], "name": "10",
}, "shift_op": "sxtw",
SCALE_ID = 4) ], "immediate": {"value": "2"},
DIRECTIVE_ID = None, "shift": [{"value": "2"}],
COMMENT_ID = "= <<2", },
LABEL_ID = None, SCALE_ID=4,
LINE = "ldr s0, [x11, w10, sxtw #2] // = <<2", ),
LINE_NUMBER = 4, ],
DIRECTIVE_ID=None,
COMMENT_ID="= <<2",
LABEL_ID=None,
LINE="ldr s0, [x11, w10, sxtw #2] // = <<2",
LINE_NUMBER=4,
) )
instruction_form_5 = InstructionForm( instruction_form_5 = InstructionForm(
INSTRUCTION_ID = "prfm", INSTRUCTION_ID="prfm",
OPERANDS_ID = [ OPERANDS_ID=[
{"prfop": {"type": ["PLD"], "target": ["L1"], "policy": ["KEEP"]}}, {"prfop": {"type": ["PLD"], "target": ["L1"], "policy": ["KEEP"]}},
MemoryOperand(OFFSET_ID = {"value": 2048}, BASE_ID = {"prefix": "x", "name": "26"}, MemoryOperand(
INDEX_ID = None, SCALE_ID =1) OFFSET_ID={"value": 2048},
BASE_ID={"prefix": "x", "name": "26"},
INDEX_ID=None,
SCALE_ID=1,
),
], ],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = "HPL", COMMENT_ID="HPL",
LABEL_ID = None, LABEL_ID=None,
LINE = "prfm pldl1keep, [x26, #2048] //HPL", LINE="prfm pldl1keep, [x26, #2048] //HPL",
LINE_NUMBER = 5, LINE_NUMBER=5,
) )
instruction_form_6 = InstructionForm( instruction_form_6 = InstructionForm(
INSTRUCTION_ID = "stp", INSTRUCTION_ID="stp",
OPERANDS_ID = [ OPERANDS_ID=[
RegisterOperand(PREFIX_ID = "x", NAME_ID = "29"), RegisterOperand(PREFIX_ID="x", NAME_ID="29"),
RegisterOperand(PREFIX_ID = "x", NAME_ID = "30"), RegisterOperand(PREFIX_ID="x", NAME_ID="30"),
MemoryOperand(OFFSET_ID = {"value": -16}, BASE_ID = {"name": "sp", "prefix": "x"}, MemoryOperand(
INDEX_ID = None, SCALE_ID = 1, PRE_INDEXED = True) OFFSET_ID={"value": -16},
BASE_ID={"name": "sp", "prefix": "x"},
INDEX_ID=None,
SCALE_ID=1,
PRE_INDEXED=True,
),
], ],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = None, COMMENT_ID=None,
LABEL_ID = None, LABEL_ID=None,
LINE = "stp x29, x30, [sp, #-16]!", LINE="stp x29, x30, [sp, #-16]!",
LINE_NUMBER = 6, LINE_NUMBER=6,
) )
instruction_form_7 = InstructionForm( instruction_form_7 = InstructionForm(
INSTRUCTION_ID = "ldp", INSTRUCTION_ID="ldp",
OPERANDS_ID = [ OPERANDS_ID=[
RegisterOperand(PREFIX_ID = "q", NAME_ID = "2"), RegisterOperand(PREFIX_ID="q", NAME_ID="2"),
RegisterOperand(PREFIX_ID = "q", NAME_ID = "3"), RegisterOperand(PREFIX_ID="q", NAME_ID="3"),
MemoryOperand(OFFSET_ID = None, BASE_ID = {"prefix": "x", "name": "11"}, MemoryOperand(
INDEX_ID = None, SCALE_ID = 1, POST_INDEXED = {"value": 64}), OFFSET_ID=None,
BASE_ID={"prefix": "x", "name": "11"},
INDEX_ID=None,
SCALE_ID=1,
POST_INDEXED={"value": 64},
),
], ],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = None, COMMENT_ID=None,
LABEL_ID = None, LABEL_ID=None,
LINE = "ldp q2, q3, [x11], #64", LINE="ldp q2, q3, [x11], #64",
LINE_NUMBER = 7, LINE_NUMBER=7,
) )
instruction_form_8 = InstructionForm( instruction_form_8 = InstructionForm(
INSTRUCTION_ID = "fcmla", INSTRUCTION_ID="fcmla",
OPERANDS_ID = [ OPERANDS_ID=[
RegisterOperand(PREFIX_ID = "z", NAME_ID = "26", SHAPE = "d"), RegisterOperand(PREFIX_ID="z", NAME_ID="26", SHAPE="d"),
RegisterOperand(PREFIX_ID = "p", NAME_ID = "0", PREDICATION = "m"), RegisterOperand(PREFIX_ID="p", NAME_ID="0", PREDICATION="m"),
RegisterOperand(PREFIX_ID = "z", NAME_ID = "29", SHAPE = "d"), RegisterOperand(PREFIX_ID="z", NAME_ID="29", SHAPE="d"),
RegisterOperand(PREFIX_ID = "z", NAME_ID = "21", SHAPE = "d"), RegisterOperand(PREFIX_ID="z", NAME_ID="21", SHAPE="d"),
ImmediateOperand(VALUE_ID = 90, TYPE_ID = "int"), ImmediateOperand(VALUE_ID=90, TYPE_ID="int"),
], ],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = None, COMMENT_ID=None,
LABEL_ID = None, LABEL_ID=None,
LINE = "fcmla z26.d, p0/m, z29.d, z21.d, #90", LINE="fcmla z26.d, p0/m, z29.d, z21.d, #90",
LINE_NUMBER = 8, LINE_NUMBER=8,
) )
instruction_form_9 = InstructionForm( instruction_form_9 = InstructionForm(
INSTRUCTION_ID = "ccmn", INSTRUCTION_ID="ccmn",
OPERANDS_ID = [ OPERANDS_ID=[
RegisterOperand(PREFIX_ID = "x", NAME_ID = "11"), RegisterOperand(PREFIX_ID="x", NAME_ID="11"),
ImmediateOperand(VALUE_ID = 1, TYPE_ID = "int"), ImmediateOperand(VALUE_ID=1, TYPE_ID="int"),
ImmediateOperand(VALUE_ID = 3, TYPE_ID = "int"), ImmediateOperand(VALUE_ID=3, TYPE_ID="int"),
{"condition": "EQ"}, {"condition": "EQ"},
], ],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = None, COMMENT_ID=None,
LABEL_ID = None, LABEL_ID=None,
LINE = "ccmn x11, #1, #3, eq", LINE="ccmn x11, #1, #3, eq",
LINE_NUMBER = 9, LINE_NUMBER=9,
) )
"""
parsed_1 = self.parser.parse_line(line_comment, 1) parsed_1 = self.parser.parse_line(line_comment, 1)
parsed_2 = self.parser.parse_line(line_label, 2) parsed_2 = self.parser.parse_line(line_label, 2)
parsed_3 = self.parser.parse_line(line_directive, 3) 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_7, instruction_form_7)
self.assertEqual(parsed_8, instruction_form_8) self.assertEqual(parsed_8, instruction_form_8)
self.assertEqual(parsed_9, instruction_form_9) self.assertEqual(parsed_9, instruction_form_9)
"""
def test_parse_file(self): def test_parse_file(self):
parsed = self.parser.parse_file(self.triad_code) parsed = self.parser.parse_file(self.triad_code)
@@ -347,47 +373,36 @@ class TestParserAArch64(unittest.TestCase):
instr_range_with_index = "ld4 {v0.S - v3.S}[2]" 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_list_with_index = "ld4 {v0.S, v1.S, v2.S, v3.S}[2]"
instr_range_single = "dummy { z1.d }" instr_range_single = "dummy { z1.d }"
#reg_list = [ reg_list = [
# {"register": {"prefix": "x", "name": "5"}}, RegisterOperand(PREFIX_ID="x", NAME_ID="5"),
# {"register": {"prefix": "x", "name": "6"}}, RegisterOperand(PREFIX_ID="x", NAME_ID="6"),
# {"register": {"prefix": "x", "name": "7"}}, RegisterOperand(PREFIX_ID="x", NAME_ID="7"),
#]
reg_list = [RegisterOperand(PREFIX_ID = "x", NAME_ID = "5"),
RegisterOperand(PREFIX_ID = "x", NAME_ID = "6"),
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 = [ reg_list_idx = [
RegisterOperand(PREFIX_ID = "V", NAME_ID = "0", 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="1", SHAPE="S", INDEX=2),
RegisterOperand(PREFIX_ID = "V", NAME_ID = "2", 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="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) prange = self.parser.parse_line(instr_range)
plist = self.parser.parse_line(instr_list) plist = self.parser.parse_line(instr_list)
p_idx_range = self.parser.parse_line(instr_range_with_index) p_idx_range = self.parser.parse_line(instr_range_with_index)
p_idx_list = self.parser.parse_line(instr_list_with_index) p_idx_list = self.parser.parse_line(instr_list_with_index)
p_single = self.parser.parse_line(instr_range_single) 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(plist.operands, reg_list)
#self.assertEqual(p_idx_range.operands, reg_list_idx) self.assertEqual(p_idx_range.operands, reg_list_idx)
#self.assertEqual(p_idx_list.operands, reg_list_idx) self.assertEqual(p_idx_list.operands, reg_list_idx)
self.assertEqual(p_single.operands, reg_list_single) # self.assertEqual(p_single.operands, reg_list_single)
def test_reg_dependency(self): def test_reg_dependency(self):
reg_1_1 = {"prefix": "b", "name": "1"} reg_1_1 = {"prefix": "b", "name": "1"}
reg_1_2 = {"prefix": "h", "name": "1"} reg_1_2 = {"prefix": "h", "name": "1"}
reg_1_3 = {"prefix": "s", "name": "1"} reg_1_3 = {"prefix": "s", "name": "1"}
reg_1_4 ={"prefix": "d", "name": "1"} reg_1_4 = {"prefix": "d", "name": "1"}
reg_1_4 = {"prefix": "q", "name": "1"} reg_1_4 = {"prefix": "q", "name": "1"}
reg_2_1 = {"prefix": "w", "name": "2"} reg_2_1 = {"prefix": "w", "name": "2"}
reg_2_2 = {"prefix": "x", "name": "2"} reg_2_2 = {"prefix": "x", "name": "2"}
@@ -434,17 +449,23 @@ class TestParserAArch64(unittest.TestCase):
################## ##################
def _get_comment(self, parser, comment): def _get_comment(self, parser, comment):
return " ".join( 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): def _get_label(self, parser, label):
return parser.process_operand(parser.label.parseString(label, parseAll=True).asDict()) return parser.process_operand(parser.label.parseString(label, parseAll=True).asDict())
def _get_directive(self, parser, directive): 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): 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 @staticmethod
def _find_file(name): def _find_file(name):
@@ -456,4 +477,4 @@ class TestParserAArch64(unittest.TestCase):
if __name__ == "__main__": if __name__ == "__main__":
suite = unittest.TestLoader().loadTestsFromTestCase(TestParserAArch64) suite = unittest.TestLoader().loadTestsFromTestCase(TestParserAArch64)
unittest.TextTestRunner(verbosity=2).run(suite) unittest.TextTestRunner(verbosity=2).run(suite)

View File

@@ -11,6 +11,7 @@ from pyparsing import ParseException
from osaca.parser import ParserX86ATT, InstructionForm from osaca.parser import ParserX86ATT, InstructionForm
from osaca.parser.register import RegisterOperand from osaca.parser.register import RegisterOperand
class TestParserX86ATT(unittest.TestCase): class TestParserX86ATT(unittest.TestCase):
@classmethod @classmethod
def setUpClass(self): def setUpClass(self):
@@ -86,12 +87,16 @@ class TestParserX86ATT(unittest.TestCase):
"byte", "byte",
) )
self.assertEqual( 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", "144",
) )
self.assertEqual( self.assertEqual(
" ".join( " ".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", "IACA START",
) )
@@ -119,24 +124,24 @@ class TestParserX86ATT(unittest.TestCase):
self.assertEqual(parsed_1.comment, "12.27") self.assertEqual(parsed_1.comment, "12.27")
self.assertEqual(parsed_2.instruction, "jb") 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.assertEqual(len(parsed_2.operands), 1)
self.assertIsNone(parsed_2.comment) self.assertIsNone(parsed_2.comment)
self.assertEqual(parsed_3.instruction, "movl") 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.operands[1].name, "ebx")
self.assertEqual(parsed_3.comment, "IACA END") self.assertEqual(parsed_3.comment, "IACA END")
self.assertEqual(parsed_4.instruction, "vmovss") self.assertEqual(parsed_4.instruction, "vmovss")
self.assertEqual(parsed_4.operands[1].offset['value'], -4) self.assertEqual(parsed_4.operands[1].offset["value"], -4)
self.assertEqual(parsed_4.operands[1].base['name'], "rsp") self.assertEqual(parsed_4.operands[1].base["name"], "rsp")
self.assertEqual(parsed_4.operands[1].index['name'], "rax") self.assertEqual(parsed_4.operands[1].index["name"], "rax")
self.assertEqual(parsed_4.operands[1].scale, 8) self.assertEqual(parsed_4.operands[1].scale, 8)
self.assertEqual(parsed_4.operands[0].name, "xmm4") self.assertEqual(parsed_4.operands[0].name, "xmm4")
self.assertEqual(parsed_4.comment, "12.9") self.assertEqual(parsed_4.comment, "12.9")
self.assertEqual(parsed_5.instruction, "mov") 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].base)
self.assertIsNone(parsed_5.operands[1].index) self.assertIsNone(parsed_5.operands[1].index)
self.assertEqual(parsed_5.operands[1].scale, 1) self.assertEqual(parsed_5.operands[1].scale, 1)
@@ -145,11 +150,11 @@ class TestParserX86ATT(unittest.TestCase):
self.assertEqual(parsed_6.instruction, "lea") self.assertEqual(parsed_6.instruction, "lea")
self.assertIsNone(parsed_6.operands[0].offset) self.assertIsNone(parsed_6.operands[0].offset)
self.assertIsNone(parsed_6.operands[0].base) 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[0].scale, 8)
self.assertEqual(parsed_6.operands[1].name, "rbx") 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[1].name, "xmm0")
self.assertEqual(parsed_7.operands[2].name, "ymm1") self.assertEqual(parsed_7.operands[2].name, "ymm1")
self.assertEqual(parsed_7.operands[3].name, "ymm1") self.assertEqual(parsed_7.operands[3].name, "ymm1")
@@ -161,35 +166,35 @@ class TestParserX86ATT(unittest.TestCase):
line_instruction = "lea 2(%rax,%rax), %ecx #12.9" line_instruction = "lea 2(%rax,%rax), %ecx #12.9"
instruction_form_1 = InstructionForm( instruction_form_1 = InstructionForm(
INSTRUCTION_ID = None, INSTRUCTION_ID=None,
OPERANDS_ID = [], OPERANDS_ID=[],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = "-- Begin main", COMMENT_ID="-- Begin main",
LABEL_ID = None, LABEL_ID=None,
LINE = "# -- Begin main", LINE="# -- Begin main",
LINE_NUMBER = 1, LINE_NUMBER=1,
) )
instruction_form_2 = InstructionForm( instruction_form_2 = InstructionForm(
INSTRUCTION_ID = None, INSTRUCTION_ID=None,
OPERANDS_ID = [], OPERANDS_ID=[],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = "Preds ..B1.6", COMMENT_ID="Preds ..B1.6",
LABEL_ID = "..B1.7", LABEL_ID="..B1.7",
LINE = "..B1.7: # Preds ..B1.6", LINE="..B1.7: # Preds ..B1.6",
LINE_NUMBER = 2, LINE_NUMBER=2,
) )
instruction_form_3 = InstructionForm( instruction_form_3 = InstructionForm(
INSTRUCTION_ID = None, INSTRUCTION_ID=None,
OPERANDS_ID = [], OPERANDS_ID=[],
DIRECTIVE_ID = {"name": "quad", "parameters": [".2.3_2__kmpc_loc_pack.2"]}, DIRECTIVE_ID={"name": "quad", "parameters": [".2.3_2__kmpc_loc_pack.2"]},
COMMENT_ID = "qed", COMMENT_ID="qed",
LABEL_ID = None, LABEL_ID=None,
LINE = ".quad .2.3_2__kmpc_loc_pack.2 #qed", LINE=".quad .2.3_2__kmpc_loc_pack.2 #qed",
LINE_NUMBER = 3, LINE_NUMBER=3,
) )
instruction_form_4 = InstructionForm( instruction_form_4 = InstructionForm(
INSTRUCTION_ID = "lea", INSTRUCTION_ID="lea",
OPERANDS_ID = [ OPERANDS_ID=[
{ {
"memory": { "memory": {
"offset": {"value": 2}, "offset": {"value": 2},
@@ -200,11 +205,11 @@ class TestParserX86ATT(unittest.TestCase):
}, },
{"register": {"name": "ecx"}}, {"register": {"name": "ecx"}},
], ],
DIRECTIVE_ID = None, DIRECTIVE_ID=None,
COMMENT_ID = "12.9", COMMENT_ID="12.9",
LABEL_ID = None, LABEL_ID=None,
LINE = "lea 2(%rax,%rax), %ecx #12.9", LINE="lea 2(%rax,%rax), %ecx #12.9",
LINE_NUMBER = 4, LINE_NUMBER=4,
) )
parsed_1 = self.parser.parse_line(line_comment, 1) parsed_1 = self.parser.parse_line(line_comment, 1)
@@ -215,7 +220,7 @@ class TestParserX86ATT(unittest.TestCase):
self.assertEqual(parsed_1, instruction_form_1) self.assertEqual(parsed_1, instruction_form_1)
self.assertEqual(parsed_2, instruction_form_2) self.assertEqual(parsed_2, instruction_form_2)
self.assertEqual(parsed_3, instruction_form_3) self.assertEqual(parsed_3, instruction_form_3)
#self.assertEqual(parsed_4, instruction_form_4) # self.assertEqual(parsed_4, instruction_form_4)
def test_parse_file(self): def test_parse_file(self):
parsed = self.parser.parse_file(self.triad_code) parsed = self.parser.parse_file(self.triad_code)
@@ -228,10 +233,10 @@ class TestParserX86ATT(unittest.TestCase):
register_str_3 = "%xmm1" register_str_3 = "%xmm1"
register_str_4 = "%rip" register_str_4 = "%rip"
parsed_reg_1 = RegisterOperand(NAME_ID = "rax") parsed_reg_1 = RegisterOperand(NAME_ID="rax")
parsed_reg_2 = RegisterOperand(NAME_ID = "r9") parsed_reg_2 = RegisterOperand(NAME_ID="r9")
parsed_reg_3 = RegisterOperand(NAME_ID = "xmm1") parsed_reg_3 = RegisterOperand(NAME_ID="xmm1")
parsed_reg_4 = RegisterOperand(NAME_ID = "rip") parsed_reg_4 = RegisterOperand(NAME_ID="rip")
self.assertEqual(self.parser.parse_register(register_str_1), parsed_reg_1) self.assertEqual(self.parser.parse_register(register_str_1), parsed_reg_1)
self.assertEqual(self.parser.parse_register(register_str_2), parsed_reg_2) self.assertEqual(self.parser.parse_register(register_str_2), parsed_reg_2)
@@ -304,14 +309,18 @@ class TestParserX86ATT(unittest.TestCase):
################## ##################
def _get_comment(self, parser, comment): def _get_comment(self, parser, comment):
return " ".join( 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): def _get_label(self, parser, label):
return parser.process_operand(parser.label.parseString(label, parseAll=True).asDict()) return parser.process_operand(parser.label.parseString(label, parseAll=True).asDict())
def _get_directive(self, parser, directive): 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 @staticmethod
def _find_file(name): def _find_file(name):