Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ jobs:
python-version: ${{ matrix.python-version}}
- name: Run tests
run: |
python3 -W error test.py
python3 -W error test.py
198 changes: 180 additions & 18 deletions slothy/targets/arm_v81m/arch_v81m.py

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add the newly added instructions also to instructions.s, so we are testing if this actually works as expected.

Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class RegisterType(Enum):
StackMVE = (3,)
StackGPR = (4,)
HINT = (5,)
FLAGS = (6,)

def __str__(self):
return self.name
Expand All @@ -74,6 +75,8 @@ def is_renamed(ty):
"""Indicate if register type should be subject to renaming"""
if ty == RegisterType.HINT:
return False
if ty == RegisterType.FLAGS:
return False
return True

@staticmethod
Expand Down Expand Up @@ -111,6 +114,7 @@ def list_registers(
RegisterType.StackMVE: qstack_locations,
RegisterType.MVE: vregs,
RegisterType.HINT: [],
RegisterType.FLAGS: ["flags"],
}[reg_type]

@staticmethod
Expand All @@ -133,14 +137,17 @@ def from_string(string):
"mve": RegisterType.MVE,
"gpr": RegisterType.GPR,
"hint": RegisterType.HINT,
"flags": RegisterType.FLAGS,
}.get(string, None)

def default_aliases():
return {"lr": "r14", "sp": "r13"}

def default_reserved():
"""Return the list of registers that should be reserved by default"""
return set(["r13", "r14"] + RegisterType.list_registers(RegisterType.HINT))
return set(
["flags", "r13", "r14"] + RegisterType.list_registers(RegisterType.HINT)
)


class LeLoop(Loop):
Expand Down Expand Up @@ -375,6 +382,7 @@ def is_load_store_instruction(self):
strd,
strd_with_writeback,
strd_with_post,
str_reg,
qsave,
qrestore,
save,
Expand Down Expand Up @@ -715,14 +723,13 @@ def __init__(
arg_types_out = [MVEInstruction._infer_register_type(r) for r in outputs]
arg_types_in_out = [MVEInstruction._infer_register_type(r) for r in in_outs]

# TODO: add flags
# if modifiesFlags:
# arg_types_out += [RegisterType.FLAGS]
# outputs += ["flags"]
if modifiesFlags:
arg_types_out += [RegisterType.FLAGS]
outputs += ["flags"]

# if dependsOnFlags:
# arg_types_in += [RegisterType.FLAGS]
# inputs += ["flags"]
if dependsOnFlags:
arg_types_in += [RegisterType.FLAGS]
inputs += ["flags"]

super().__init__(
mnemonic=pattern,
Expand All @@ -745,6 +752,8 @@ def __init__(

@staticmethod
def _to_reg(ty, s):
if ty == RegisterType.FLAGS:
return "flags"
if ty == RegisterType.GPR:
c = "r"
elif ty == RegisterType.MVE:
Expand All @@ -769,8 +778,8 @@ def _build_pattern_replacement(s, ty, arg):

@staticmethod
def _instantiate_pattern(s, ty, arg, out):
# if ty == RegisterType.FLAGS:
# return out
if ty == RegisterType.FLAGS:
return out
rep = MVEInstruction._build_pattern_replacement(s, ty, arg)
res = out.replace(f"<{s}>", rep)
if res == out:
Expand Down Expand Up @@ -808,15 +817,15 @@ def group_name_i(i):
group_to_attribute("barrel", "barrel")

for s, ty in obj.pattern_inputs:
# if ty == RegisterType.FLAGS:
# obj.args_in.append("flags")
# else:
obj.args_in.append(MVEInstruction._to_reg(ty, res[s]))
if ty == RegisterType.FLAGS:
obj.args_in.append("flags")
else:
obj.args_in.append(MVEInstruction._to_reg(ty, res[s]))
for s, ty in obj.pattern_outputs:
# if ty == RegisterType.FLAGS:
# obj.args_out.append("flags")
# else:
obj.args_out.append(MVEInstruction._to_reg(ty, res[s]))
if ty == RegisterType.FLAGS:
obj.args_out.append("flags")
else:
obj.args_out.append(MVEInstruction._to_reg(ty, res[s]))

for s, ty in obj.pattern_in_outs:
obj.args_in_out.append(MVEInstruction._to_reg(ty, res[s]))
Expand Down Expand Up @@ -1042,6 +1051,47 @@ class eor_shifted(MVEInstruction):
outputs = ["Rd"]


class bic(MVEInstruction):
pattern = "bic <Rd>, <Rn>, <Rm>"
inputs = ["Rn", "Rm"]
outputs = ["Rd"]


class bic_shifted(MVEInstruction):
pattern = "bic <Rd>, <Rn>, <Rm>, <barrel> <imm>"
inputs = ["Rn", "Rm"]
outputs = ["Rd"]


class ror(MVEInstruction):
pattern = "ror <Rd>, <Rn>, <Rm>"
inputs = ["Rn", "Rm"]
outputs = ["Rd"]


class ror_imm(MVEInstruction):
pattern = "ror <Rd>, <Rn>, <imm>"
inputs = ["Rn"]
outputs = ["Rd"]


class ror_short(MVEInstruction):
pattern = "ror <Rd>, <imm>"
in_outs = ["Rd"]


class cmp_reg(MVEInstruction):
pattern = "cmp <Rn>, <Rm>"
inputs = ["Rn", "Rm"]
modifiesFlags = True


class cmp_imm(MVEInstruction):
pattern = "cmp <Rn>, <imm>"
inputs = ["Rn"]
modifiesFlags = True


class sub(MVEInstruction):
pattern = "sub <Rd>, <Rn>, <Rm>"
inputs = ["Rn", "Rm"]
Expand Down Expand Up @@ -1296,6 +1346,19 @@ def make(cls, src):
return obj


class str_reg(MVEInstruction):
pattern = "str <Rt>, [<Rn>, <imm>]"
inputs = ["Rn", "Rt"]

@classmethod
def make(cls, src):
obj = MVEInstruction.build(cls, src)
obj.increment = None
obj.pre_index = obj.immediate
obj.addr = obj.args_in[0]
return obj


class vrshr(MVEInstruction):
pattern = "vrshr.<dt> <Qd>, <Qm>, <imm>"
inputs = ["Qm"]
Expand Down Expand Up @@ -1348,6 +1411,26 @@ class vmov_double_v2r(MVEInstruction):
outputs = ["Rt0", "Rt1"]


class vmov_double_r2v(MVEInstruction):
pattern = "vmov <Qd>[<index0>], <Qa>[<index1>], <Rt0>, <Rt1>"
inputs = ["Rt0", "Rt1"]
in_outs = ["Qd", "Qa"]

@classmethod
def make(cls, src):
obj = MVEInstruction.build(cls, src)
if len(obj.args_in_out) == 2 and obj.args_in_out[0] == obj.args_in_out[1]:
obj.pattern = "vmov <Qd>[<index0>], <Qd>[<index1>], <Rt0>, <Rt1>"
obj.args_in_out = [obj.args_in_out[0]]
obj.arg_types_in_out = [obj.arg_types_in_out[0]]
obj.args_in_out_restrictions = [obj.args_in_out_restrictions[0]]
obj.in_outs = [obj.in_outs[0]]
obj.pattern_in_outs = [obj.pattern_in_outs[0]]
obj.num_in_out = 1
obj.detected_vmov_double_r2v_pair = False
return obj


class mov(MVEInstruction):
pattern = "mov <Rd>, <Rm>"
inputs = ["Rm"]
Expand Down Expand Up @@ -1448,6 +1531,12 @@ class vsli(MVEInstruction):
in_outs = ["Qd"]


class vsri(MVEInstruction):
pattern = "vsri.<dt> <Qd>, <Qm>, <imm>"
inputs = ["Qm"]
in_outs = ["Qd"]


class vmovlb(MVEInstruction):
pattern = "vmovlb.<dt> <Qd>, <Qm>"
inputs = ["Qm"]
Expand Down Expand Up @@ -2661,6 +2750,79 @@ def core(inst, t, log=None):
vqdmladhx.global_parsing_cb = vqdmlsdh_vqdmladhx_parsing_cb(vqdmladhx, vqdmlsdh)


def vmov_double_r2v_parsing_cb(this_class):
def mark_outputs_only(inst):
inst.num_out = len(inst.args_in_out)
inst.args_out = list(inst.args_in_out)
inst.arg_types_out = [RegisterType.MVE for _ in inst.args_in_out]
inst.args_out_restrictions = list(inst.args_in_out_restrictions)
inst.outputs = list(inst.in_outs)
inst.pattern_outputs = list(inst.pattern_in_outs)

inst.num_in_out = 0
inst.args_in_out = []
inst.in_outs = []
inst.pattern_in_outs = []
inst.arg_types_in_out = []
inst.args_in_out_restrictions = []

inst.detected_vmov_double_r2v_pair = True

def core(inst, t, log=None):
# Special-case two vmov r2v that jointly overwrite q*.
# Conditions:
# - Both vmovs target the same vector register
# (Qd==Qa, and equal across the pair)
# - The two vmovs jointly cover all lanes {0,1,2,3}
# - The first vmov has exactly one in/out data-flow successor, which
# is the second vmov. Unrelated intervening instructions are allowed;
# intervening q-register consumers are not.

assert isinstance(inst, this_class)
if getattr(inst, "detected_vmov_double_r2v_pair", False):
return False
if getattr(inst, "detected_vmov_double_r2v_pair_successor", False):
return False

if len(t.dst_in_out) != 1 or len(t.dst_in_out[0]) != 1:
return False
succ = t.dst_in_out[0][0]
if not isinstance(succ.inst, this_class):
return False

same_q_this = hasattr(inst, "args_in_out") and len(inst.args_in_out) == 1
same_q_next = (
hasattr(succ.inst, "args_in_out") and len(succ.inst.args_in_out) == 1
)
same_q_across = (
same_q_this
and same_q_next
and (inst.args_in_out[0] == succ.inst.args_in_out[0])
)

idx_this = getattr(inst, "index", None)
idx_next = getattr(succ.inst, "index", None)
full_cover = (
isinstance(idx_this, list)
and isinstance(idx_next, list)
and len(idx_this) == 2
and len(idx_next) == 2
and set(idx_this + idx_next) == {0, 1, 2, 3}
)

if not (same_q_across and full_cover):
return False

mark_outputs_only(inst)
succ.inst.detected_vmov_double_r2v_pair_successor = True
return True

return core


vmov_double_r2v.global_parsing_cb = vmov_double_r2v_parsing_cb(vmov_double_r2v)


# Returns the list of all subclasses of a class which don't have
# subclasses themselves
def all_subclass_leaves(c):
Expand Down
Loading
Loading