mirror of
https://github.com/RRZE-HPC/OSACA.git
synced 2025-12-15 16:40:05 +01:00
124 lines
4.3 KiB
Python
124 lines
4.3 KiB
Python
import re
|
|
import string
|
|
|
|
from osaca.parser import BaseParser
|
|
|
|
|
|
class ParserX86(BaseParser):
|
|
_instance = None
|
|
|
|
# Singleton pattern, as this is created very many times.
|
|
def __new__(cls):
|
|
if cls._instance is None:
|
|
cls._instance = super(ParserX86, cls).__new__(cls)
|
|
return cls._instance
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
def isa(self):
|
|
return "x86"
|
|
|
|
def is_reg_dependend_of(self, reg_a, reg_b):
|
|
"""Check if ``reg_a`` is dependent on ``reg_b``"""
|
|
reg_a_name = reg_a.name.upper()
|
|
reg_b_name = reg_b.name.upper()
|
|
|
|
# Check if they are the same registers
|
|
if reg_a_name == reg_b_name:
|
|
return True
|
|
# Check vector registers first
|
|
if self.is_vector_register(reg_a):
|
|
if self.is_vector_register(reg_b):
|
|
if reg_a_name[1:] == reg_b_name[1:]:
|
|
# Registers in the same vector space
|
|
return True
|
|
return False
|
|
# Check basic GPRs
|
|
gpr_groups = {
|
|
"A": ["RAX", "EAX", "AX", "AH", "AL"],
|
|
"B": ["RBX", "EBX", "BX", "BH", "BL"],
|
|
"C": ["RCX", "ECX", "CX", "CH", "CL"],
|
|
"D": ["RDX", "EDX", "DX", "DH", "DL"],
|
|
"SP": ["RSP", "ESP", "SP", "SPL"],
|
|
"SRC": ["RSI", "ESI", "SI", "SIL"],
|
|
"DST": ["RDI", "EDI", "DI", "DIL"],
|
|
}
|
|
if self.is_basic_gpr(reg_a):
|
|
if self.is_basic_gpr(reg_b):
|
|
for dep_group in gpr_groups.values():
|
|
if reg_a_name in dep_group:
|
|
if reg_b_name in dep_group:
|
|
return True
|
|
return False
|
|
|
|
# Check other GPRs
|
|
ma = re.match(r"R([0-9]+)[DWB]?", reg_a_name)
|
|
mb = re.match(r"R([0-9]+)[DWB]?", reg_b_name)
|
|
if ma and mb and ma.group(1) == mb.group(1):
|
|
return True
|
|
|
|
# No dependencies
|
|
return False
|
|
|
|
def is_basic_gpr(self, register):
|
|
"""Check if register is a basic general purpose register (ebi, rax, ...)"""
|
|
if any(char.isdigit() for char in register.name) or any(
|
|
register.name.lower().startswith(x) for x in ["mm", "xmm", "ymm", "zmm"]
|
|
):
|
|
return False
|
|
return True
|
|
|
|
def is_gpr(self, register):
|
|
"""Check if register is a general purpose register"""
|
|
if register is None:
|
|
return False
|
|
if self.is_basic_gpr(register):
|
|
return True
|
|
return re.match(r"R([0-9]+)[DWB]?", register.name, re.IGNORECASE)
|
|
|
|
def is_vector_register(self, register):
|
|
"""Check if register is a vector register"""
|
|
if register is None or register.name is None:
|
|
return False
|
|
if register.name.rstrip(string.digits).lower() in [
|
|
"mm",
|
|
"xmm",
|
|
"ymm",
|
|
"zmm",
|
|
]:
|
|
return True
|
|
return False
|
|
|
|
def get_reg_type(self, register):
|
|
"""Get register type"""
|
|
if register is None:
|
|
return False
|
|
if self.is_gpr(register):
|
|
return "gpr"
|
|
elif self.is_vector_register(register):
|
|
return register.name.rstrip(string.digits).lower()
|
|
raise ValueError
|
|
|
|
def is_flag_dependend_of(self, flag_a, flag_b):
|
|
"""Check if ``flag_a`` is dependent on ``flag_b``"""
|
|
# we assume flags are independent of each other, e.g., CF can be read while ZF gets written
|
|
# TODO validate this assumption
|
|
return flag_a.name == flag_b.name
|
|
|
|
def get_regular_source_operands(self, instruction_form):
|
|
"""Get source operand of given instruction form assuming regular src/dst behavior."""
|
|
# if there is only one operand, assume it is a source operand
|
|
if len(instruction_form.operands) == 1:
|
|
return [instruction_form.operands[0]]
|
|
# return all but last operand
|
|
return [op for op in instruction_form.operands[0:-1]]
|
|
|
|
def get_regular_destination_operands(self, instruction_form):
|
|
"""Get destination operand of given instruction form assuming regular src/dst behavior."""
|
|
# if there is only one operand, assume no destination
|
|
if len(instruction_form.operands) == 1:
|
|
return []
|
|
# return last operand
|
|
return instruction_form.operands[-1:]
|