jukefa-asmgen 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- asmgen/__init__.py +5 -0
- asmgen/asmblocks/__init__.py +8 -0
- asmgen/asmblocks/aarch64/__init__.py +9 -0
- asmgen/asmblocks/aarch64/gen.py +259 -0
- asmgen/asmblocks/aarch64/opmem/__init__.py +11 -0
- asmgen/asmblocks/aarch64/opmem/base.py +182 -0
- asmgen/asmblocks/aarch64/opmem/load.py +21 -0
- asmgen/asmblocks/aarch64/opmem/prefetch.py +40 -0
- asmgen/asmblocks/aarch64/opmem/signatures.py +134 -0
- asmgen/asmblocks/aarch64/opmem/store.py +21 -0
- asmgen/asmblocks/aarch64/opmove/__init__.py +22 -0
- asmgen/asmblocks/aarch64/opset/__init__.py +4 -0
- asmgen/asmblocks/aarch64/opset/base.py +66 -0
- asmgen/asmblocks/aarch64/opset/signatures.py +11 -0
- asmgen/asmblocks/aarch64/optransform/__init__.py +9 -0
- asmgen/asmblocks/aarch64/optransform/base.py +218 -0
- asmgen/asmblocks/aarch64/optransform/scalar.py +81 -0
- asmgen/asmblocks/aarch64/types.py +78 -0
- asmgen/asmblocks/avx/__init__.py +9 -0
- asmgen/asmblocks/avx/avx2.py +146 -0
- asmgen/asmblocks/avx/avx512.py +149 -0
- asmgen/asmblocks/avx/base.py +456 -0
- asmgen/asmblocks/avx/gen.py +12 -0
- asmgen/asmblocks/avx/opmem/__init__.py +10 -0
- asmgen/asmblocks/avx/opmem/base.py +482 -0
- asmgen/asmblocks/avx/opmem/load.py +43 -0
- asmgen/asmblocks/avx/opmem/signatures.py +190 -0
- asmgen/asmblocks/avx/opmem/store.py +75 -0
- asmgen/asmblocks/avx/opmove/__init__.py +4 -0
- asmgen/asmblocks/avx/opmove/base.py +114 -0
- asmgen/asmblocks/avx/opmove/signatures.py +94 -0
- asmgen/asmblocks/avx/opset/__init__.py +4 -0
- asmgen/asmblocks/avx/opset/base.py +93 -0
- asmgen/asmblocks/avx/opset/signatures.py +31 -0
- asmgen/asmblocks/avx/optransform/__init__.py +11 -0
- asmgen/asmblocks/avx/optransform/add.py +36 -0
- asmgen/asmblocks/avx/optransform/base.py +140 -0
- asmgen/asmblocks/avx/optransform/fma.py +20 -0
- asmgen/asmblocks/avx/optransform/mul.py +36 -0
- asmgen/asmblocks/avx/optransform/signatures.py +54 -0
- asmgen/asmblocks/avx/setup.py +21 -0
- asmgen/asmblocks/avx/types.py +115 -0
- asmgen/asmblocks/neon/__init__.py +9 -0
- asmgen/asmblocks/neon/gen.py +168 -0
- asmgen/asmblocks/neon/opmem/__init__.py +10 -0
- asmgen/asmblocks/neon/opmem/base.py +318 -0
- asmgen/asmblocks/neon/opmem/load.py +21 -0
- asmgen/asmblocks/neon/opmem/signatures.py +178 -0
- asmgen/asmblocks/neon/opmem/store.py +20 -0
- asmgen/asmblocks/neon/opmove/__init__.py +4 -0
- asmgen/asmblocks/neon/opmove/base.py +80 -0
- asmgen/asmblocks/neon/opmove/signatures.py +78 -0
- asmgen/asmblocks/neon/opset/__init__.py +4 -0
- asmgen/asmblocks/neon/opset/base.py +33 -0
- asmgen/asmblocks/neon/opset/signatures.py +18 -0
- asmgen/asmblocks/neon/optransform/__init__.py +11 -0
- asmgen/asmblocks/neon/optransform/add.py +39 -0
- asmgen/asmblocks/neon/optransform/base.py +67 -0
- asmgen/asmblocks/neon/optransform/fma.py +37 -0
- asmgen/asmblocks/neon/optransform/mul.py +46 -0
- asmgen/asmblocks/neon/optransform/signatures.py +185 -0
- asmgen/asmblocks/neon/types.py +23 -0
- asmgen/asmblocks/noarch.py +811 -0
- asmgen/asmblocks/op/__init__.py +44 -0
- asmgen/asmblocks/op/constraint.py +441 -0
- asmgen/asmblocks/op/domain.py +275 -0
- asmgen/asmblocks/op/misc.py +17 -0
- asmgen/asmblocks/op/modifier.py +15 -0
- asmgen/asmblocks/op/operand.py +129 -0
- asmgen/asmblocks/op/operation.py +296 -0
- asmgen/asmblocks/op/opmem.py +163 -0
- asmgen/asmblocks/op/opmove.py +151 -0
- asmgen/asmblocks/op/opset.py +370 -0
- asmgen/asmblocks/op/optransform.py +154 -0
- asmgen/asmblocks/op/scalar.py +223 -0
- asmgen/asmblocks/op/shift.py +90 -0
- asmgen/asmblocks/op/signature.py +211 -0
- asmgen/asmblocks/riscv64/__init__.py +9 -0
- asmgen/asmblocks/riscv64/gen.py +222 -0
- asmgen/asmblocks/riscv64/opmem/__init__.py +11 -0
- asmgen/asmblocks/riscv64/opmem/base.py +150 -0
- asmgen/asmblocks/riscv64/opmem/load.py +20 -0
- asmgen/asmblocks/riscv64/opmem/prefetch.py +40 -0
- asmgen/asmblocks/riscv64/opmem/signatures.py +99 -0
- asmgen/asmblocks/riscv64/opmem/store.py +20 -0
- asmgen/asmblocks/riscv64/opmove/__init__.py +20 -0
- asmgen/asmblocks/riscv64/opset/__init__.py +4 -0
- asmgen/asmblocks/riscv64/opset/base.py +24 -0
- asmgen/asmblocks/riscv64/opset/signatures.py +11 -0
- asmgen/asmblocks/riscv64/optransform/__init__.py +67 -0
- asmgen/asmblocks/riscv64/types.py +68 -0
- asmgen/asmblocks/rvv/__init__.py +9 -0
- asmgen/asmblocks/rvv/gen.py +191 -0
- asmgen/asmblocks/rvv/opmem/__init__.py +10 -0
- asmgen/asmblocks/rvv/opmem/base.py +301 -0
- asmgen/asmblocks/rvv/opmem/load.py +27 -0
- asmgen/asmblocks/rvv/opmem/signatures.py +214 -0
- asmgen/asmblocks/rvv/opmem/store.py +24 -0
- asmgen/asmblocks/rvv/opmove/__init__.py +4 -0
- asmgen/asmblocks/rvv/opmove/base.py +79 -0
- asmgen/asmblocks/rvv/opmove/signatures.py +77 -0
- asmgen/asmblocks/rvv/opset/__init__.py +4 -0
- asmgen/asmblocks/rvv/opset/base.py +54 -0
- asmgen/asmblocks/rvv/opset/signatures.py +18 -0
- asmgen/asmblocks/rvv/optransform/__init__.py +11 -0
- asmgen/asmblocks/rvv/optransform/add.py +22 -0
- asmgen/asmblocks/rvv/optransform/base.py +198 -0
- asmgen/asmblocks/rvv/optransform/fma.py +30 -0
- asmgen/asmblocks/rvv/optransform/mul.py +22 -0
- asmgen/asmblocks/rvv/optransform/signatures.py +116 -0
- asmgen/asmblocks/rvv/setup.py +82 -0
- asmgen/asmblocks/rvv/types.py +24 -0
- asmgen/asmblocks/rvv071/__init__.py +9 -0
- asmgen/asmblocks/rvv071/gen.py +90 -0
- asmgen/asmblocks/rvv071/opmem.py +61 -0
- asmgen/asmblocks/rvv071/opmove.py +33 -0
- asmgen/asmblocks/rvv071/setup.py +18 -0
- asmgen/asmblocks/setup.py +168 -0
- asmgen/asmblocks/sme/__init__.py +9 -0
- asmgen/asmblocks/sme/gen.py +115 -0
- asmgen/asmblocks/sme/opmem/__init__.py +10 -0
- asmgen/asmblocks/sme/opmem/base.py +247 -0
- asmgen/asmblocks/sme/opmem/load.py +21 -0
- asmgen/asmblocks/sme/opmem/signatures.py +199 -0
- asmgen/asmblocks/sme/opmem/store.py +21 -0
- asmgen/asmblocks/sme/opmove/__init__.py +10 -0
- asmgen/asmblocks/sme/opmove/base.py +188 -0
- asmgen/asmblocks/sme/opmove/signatures.py +248 -0
- asmgen/asmblocks/sme/opset/__init__.py +4 -0
- asmgen/asmblocks/sme/opset/base.py +31 -0
- asmgen/asmblocks/sme/opset/signatures.py +16 -0
- asmgen/asmblocks/sme/optransform/__init__.py +10 -0
- asmgen/asmblocks/sme/optransform/fopa.py +108 -0
- asmgen/asmblocks/sme/optransform/signatures.py +118 -0
- asmgen/asmblocks/sme/setup.py +68 -0
- asmgen/asmblocks/sme/types.py +35 -0
- asmgen/asmblocks/sve/__init__.py +9 -0
- asmgen/asmblocks/sve/gen.py +161 -0
- asmgen/asmblocks/sve/opmem/__init__.py +10 -0
- asmgen/asmblocks/sve/opmem/base.py +249 -0
- asmgen/asmblocks/sve/opmem/load.py +23 -0
- asmgen/asmblocks/sve/opmem/signatures.py +192 -0
- asmgen/asmblocks/sve/opmem/store.py +21 -0
- asmgen/asmblocks/sve/opmove/__init__.py +11 -0
- asmgen/asmblocks/sve/opmove/base.py +120 -0
- asmgen/asmblocks/sve/opmove/signatures.py +130 -0
- asmgen/asmblocks/sve/opset/__init__.py +4 -0
- asmgen/asmblocks/sve/opset/base.py +52 -0
- asmgen/asmblocks/sve/opset/signatures.py +31 -0
- asmgen/asmblocks/sve/optransform/__init__.py +11 -0
- asmgen/asmblocks/sve/optransform/add.py +39 -0
- asmgen/asmblocks/sve/optransform/base.py +44 -0
- asmgen/asmblocks/sve/optransform/fma.py +19 -0
- asmgen/asmblocks/sve/optransform/mul.py +40 -0
- asmgen/asmblocks/sve/optransform/scalar.py +20 -0
- asmgen/asmblocks/sve/optransform/signatures.py +189 -0
- asmgen/asmblocks/sve/setup.py +48 -0
- asmgen/asmblocks/sve/types.py +39 -0
- asmgen/asmblocks/x86/__init__.py +8 -0
- asmgen/asmblocks/x86/opmem/__init__.py +11 -0
- asmgen/asmblocks/x86/opmem/base.py +162 -0
- asmgen/asmblocks/x86/opmem/displacement.py +57 -0
- asmgen/asmblocks/x86/opmem/load.py +23 -0
- asmgen/asmblocks/x86/opmem/prefetch.py +41 -0
- asmgen/asmblocks/x86/opmem/signatures.py +129 -0
- asmgen/asmblocks/x86/opmem/store.py +23 -0
- asmgen/asmblocks/x86/opmove/__init__.py +28 -0
- asmgen/asmblocks/x86/opset/__init__.py +4 -0
- asmgen/asmblocks/x86/opset/base.py +51 -0
- asmgen/asmblocks/x86/opset/signatures.py +11 -0
- asmgen/asmblocks/x86/optransform/__init__.py +109 -0
- asmgen/asmblocks/x86/types.py +95 -0
- asmgen/asmdata.py +141 -0
- asmgen/benchmark/__init__.py +5 -0
- asmgen/benchmark/extra_sources.py +11 -0
- asmgen/callconv/__init__.py +0 -0
- asmgen/callconv/callconv.py +353 -0
- asmgen/callconv/fngen.py +164 -0
- asmgen/compilation/__init__.py +5 -0
- asmgen/compilation/compiler_presets.py +127 -0
- asmgen/compilation/tools.py +164 -0
- asmgen/cppgen/__init__.py +5 -0
- asmgen/cppgen/analyzers.py +29 -0
- asmgen/cppgen/checkers.py +162 -0
- asmgen/cppgen/declarations.py +209 -0
- asmgen/cppgen/expressions.py +62 -0
- asmgen/cppgen/templates.py +163 -0
- asmgen/cppgen/types.py +25 -0
- asmgen/cppgen/writers.py +84 -0
- asmgen/emulation.py +186 -0
- asmgen/registers.py +605 -0
- asmgen/util.py +10 -0
- jukefa_asmgen-0.6.0.dist-info/METADATA +50 -0
- jukefa_asmgen-0.6.0.dist-info/RECORD +197 -0
- jukefa_asmgen-0.6.0.dist-info/WHEEL +4 -0
- jukefa_asmgen-0.6.0.dist-info/licenses/LICENSE-GPL-3.0 +674 -0
- jukefa_asmgen-0.6.0.dist-info/licenses/LICENSE-MIT +21 -0
asmgen/__init__.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
6
|
+
"""
|
|
7
|
+
Module containing ASM generator abstract class and implementations for different ISAs
|
|
8
|
+
"""
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
6
|
+
"""
|
|
7
|
+
AArch64 asm generator, register types and scalar memory ops
|
|
8
|
+
"""
|
|
9
|
+
from .gen import aarch64
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
6
|
+
"""
|
|
7
|
+
ARM64/AArch64 asm generator and related types
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from copy import deepcopy
|
|
11
|
+
from typing import Union
|
|
12
|
+
|
|
13
|
+
from ..noarch import compiler_family
|
|
14
|
+
from ..noarch import asmgen,comparison
|
|
15
|
+
from ...registers import (
|
|
16
|
+
adt_size,
|
|
17
|
+
|
|
18
|
+
asm_data_type as adt,
|
|
19
|
+
greg_base, freg_base
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from .types import aarch64_greg,aarch64_freg
|
|
23
|
+
from ...callconv.callconv import callconv
|
|
24
|
+
|
|
25
|
+
from .opmem import aarch64_load, aarch64_store
|
|
26
|
+
from .opmem import aarch64_prefetch
|
|
27
|
+
from ...registers import asm_data_type as _ADT
|
|
28
|
+
from ..op.operand import operand_modifier as _opd_mod
|
|
29
|
+
from ..op.opmove import opmove_modifier as _move_mod
|
|
30
|
+
from ..op.scalar import BITS_GP as _BITS_GP
|
|
31
|
+
from ..op.opset import opset_modifier as _opset_mod
|
|
32
|
+
from ..op.optransform import optransform_modifier as _opd3_mod
|
|
33
|
+
|
|
34
|
+
_GP = _ADT.UINT64 # general registers' arithmetic: 64-bit
|
|
35
|
+
|
|
36
|
+
class aarch64(asmgen):
|
|
37
|
+
"""
|
|
38
|
+
ARM64/AArch64 asmgen implementation
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
#: -march's base, and the features as its extensions (per backend)
|
|
42
|
+
MARCH_BASE = "armv8-a"
|
|
43
|
+
MARCH_EXTENSIONS : dict[str, str] = {}
|
|
44
|
+
|
|
45
|
+
def compiler_flags(self, compiler : str = "gcc") -> list[str]:
|
|
46
|
+
compiler_family(compiler)
|
|
47
|
+
enabled = self.enabled_features()
|
|
48
|
+
extensions = [self.MARCH_EXTENSIONS[f] for f in self.FEATURES
|
|
49
|
+
if f in enabled and f in self.MARCH_EXTENSIONS]
|
|
50
|
+
return ["-march=" + "+".join([self.MARCH_BASE] + extensions)]
|
|
51
|
+
|
|
52
|
+
#: the nop: nop
|
|
53
|
+
NOP_BYTES = 4
|
|
54
|
+
NOP_ENCODING = 0xd503201f
|
|
55
|
+
|
|
56
|
+
dt_greg_pfx = {
|
|
57
|
+
adt.DOUBLE : "x",
|
|
58
|
+
adt.SINGLE : "w",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
cb_insts = {
|
|
62
|
+
'NZ' : 'cbnz',
|
|
63
|
+
'EZ' : 'cbz',
|
|
64
|
+
'NE' : 'b.ne',
|
|
65
|
+
'EQ' : 'b.eq',
|
|
66
|
+
'LE' : 'b.le',
|
|
67
|
+
'GE' : 'b.ge',
|
|
68
|
+
'LT' : 'b.lt',
|
|
69
|
+
'GT' : 'b.gt',
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def __init__(self):
|
|
73
|
+
super().__init__()
|
|
74
|
+
self.callconvs = {
|
|
75
|
+
"aapcs64" : callconv(
|
|
76
|
+
param_regs={ 'greg' : list(range(0, 8)),
|
|
77
|
+
'freg' : list(range(0, 8))},
|
|
78
|
+
caller_save_lists={ 'greg' : list(range(0, 8)) + # func args/return vals
|
|
79
|
+
[8] + # XR, indirect result reg
|
|
80
|
+
list(range(9,16)) + # locals
|
|
81
|
+
[18] # platform reg
|
|
82
|
+
,
|
|
83
|
+
'freg' : list(range(0, 8)) +
|
|
84
|
+
list(range(16,32))
|
|
85
|
+
},
|
|
86
|
+
callee_save_lists={ 'greg' : list(range(19,29)) + # Callee-saved
|
|
87
|
+
[29, # Frame Pointer
|
|
88
|
+
30 # Link Register
|
|
89
|
+
] +
|
|
90
|
+
[31], # SP
|
|
91
|
+
'freg' : list(range(8,16))},
|
|
92
|
+
spreg=31)
|
|
93
|
+
}
|
|
94
|
+
self.load = aarch64_load(asmwrap=self.asmwrap)
|
|
95
|
+
self.store = aarch64_store(asmwrap=self.asmwrap)
|
|
96
|
+
self.prefetch = aarch64_prefetch(asmwrap=self.asmwrap)
|
|
97
|
+
self.default_callconv = "aapcs64"
|
|
98
|
+
|
|
99
|
+
def create_callconv(self, name : str = "default"):
|
|
100
|
+
|
|
101
|
+
if "default" == name:
|
|
102
|
+
name = self.default_callconv
|
|
103
|
+
|
|
104
|
+
return deepcopy(self.callconvs[name])
|
|
105
|
+
|
|
106
|
+
def label(self, *, label : str) -> str:
|
|
107
|
+
return self.asmwrap(f"{self.labelstr(label)}:")
|
|
108
|
+
|
|
109
|
+
def jump(self, *, label : str) -> str:
|
|
110
|
+
return self.asmwrap(f"b {self.labelstr(label)}")
|
|
111
|
+
|
|
112
|
+
def loopbegin(self, *, reg : greg_base,
|
|
113
|
+
label : str) -> str:
|
|
114
|
+
asmblock = self.asmwrap(f"{self.labelstr(label)}:")
|
|
115
|
+
asmblock += self.asmwrap(f"sub {reg},{reg},1")
|
|
116
|
+
return asmblock
|
|
117
|
+
|
|
118
|
+
def loopbegin_nz(self, *, reg : greg_base,
|
|
119
|
+
label : str,
|
|
120
|
+
labelskip : str) -> str:
|
|
121
|
+
asmblock = self.asmwrap(f"cmp {reg},0")
|
|
122
|
+
asmblock += self.asmwrap(f"b.eq {self.labelstr(labelskip)}")
|
|
123
|
+
asmblock += self.asmwrap(f"{self.labelstr(label)}:")
|
|
124
|
+
asmblock += self.asmwrap(f"sub {reg},{reg},1")
|
|
125
|
+
return asmblock
|
|
126
|
+
|
|
127
|
+
def loopend(self, *, reg : greg_base,
|
|
128
|
+
label : str) -> str:
|
|
129
|
+
asmblock = self.asmwrap(f"cmp {reg},0")
|
|
130
|
+
asmblock += self.asmwrap(f"b.ne {self.labelstr(label)}")
|
|
131
|
+
return asmblock
|
|
132
|
+
|
|
133
|
+
def fcb(self, *, reg1, reg2, cmp: comparison, label: str, dt: adt, greg=None) -> str:
|
|
134
|
+
"""
|
|
135
|
+
cb on FP registers: equality as floating point, so -0.0 equals 0.0
|
|
136
|
+
and NaN equals nothing
|
|
137
|
+
"""
|
|
138
|
+
insts = {'EQ': 'b.eq', 'EZ': 'b.eq', 'NE': 'b.ne', 'NZ': 'b.ne',
|
|
139
|
+
'LT': 'b.mi', 'LE': 'b.ls', 'GT': 'b.gt', 'GE': 'b.ge'}
|
|
140
|
+
other = reg2 if reg2 is not None else "#0.0"
|
|
141
|
+
return self.asmwrap(f"fcmp {reg1},{other}") + \
|
|
142
|
+
self.asmwrap(f"{insts[cmp.name]} {self.labelstr(label)}")
|
|
143
|
+
|
|
144
|
+
def cb(self, *, reg1, reg2, cmp: comparison, label: str,
|
|
145
|
+
dt: adt | None = None, greg: greg_base | None = None) -> str:
|
|
146
|
+
if isinstance(reg1, freg_base):
|
|
147
|
+
return self.fcb(reg1=reg1, reg2=reg2, cmp=cmp, label=label, dt=dt, greg=greg)
|
|
148
|
+
inst = self.cb_insts[cmp.name]
|
|
149
|
+
if reg2 is None:
|
|
150
|
+
return self.asmwrap(f"{inst} {reg1},{self.labelstr(label)}")
|
|
151
|
+
|
|
152
|
+
return self.asmwrap(f"cmp {reg1},{reg2}")+\
|
|
153
|
+
self.asmwrap(f"{inst} {self.labelstr(label)}")
|
|
154
|
+
|
|
155
|
+
def jzero(self, *, reg : greg_base,
|
|
156
|
+
label : str) -> str:
|
|
157
|
+
asmblock = self.asmwrap(f"cmp {reg},0")
|
|
158
|
+
asmblock += self.asmwrap(f"b.eq {self.labelstr(label)}")
|
|
159
|
+
return asmblock
|
|
160
|
+
|
|
161
|
+
def jfzero(self, *, freg1 : freg_base, freg2 : freg_base,
|
|
162
|
+
greg : greg_base, label : str,
|
|
163
|
+
dt : adt):
|
|
164
|
+
asmblock = self.asmwrap(f"fcmp {freg1},#0.0")
|
|
165
|
+
asmblock += self.asmwrap(f"b.eq {self.labelstr(label)}")
|
|
166
|
+
return asmblock
|
|
167
|
+
|
|
168
|
+
def shared_registers(self) -> list[tuple[str, str, dict[int, int] | None]]:
|
|
169
|
+
# a scalar FP register is the low part of the vector register
|
|
170
|
+
return [("freg", "vreg", None)]
|
|
171
|
+
|
|
172
|
+
def reserved_registers(self) -> dict[str, dict[str, int]]:
|
|
173
|
+
# x18 is the platform register on Apple and Windows
|
|
174
|
+
return {"greg": {"sp": 31, "lr": 30, "fp": 29, "platform": 18}}
|
|
175
|
+
def max_gregs(self):
|
|
176
|
+
return 32
|
|
177
|
+
def max_mregs(self):
|
|
178
|
+
return 0
|
|
179
|
+
def max_fregs(self):
|
|
180
|
+
return 32
|
|
181
|
+
|
|
182
|
+
def kiterkleft_pow2(self, *, kreg : greg_base,
|
|
183
|
+
kleftreg : greg_base,
|
|
184
|
+
unroll : int) -> str:
|
|
185
|
+
"""
|
|
186
|
+
kiterkleft variant for unroll values that are powers of 2
|
|
187
|
+
|
|
188
|
+
Can be simplified down to a "right shift" and "and"
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
asmblock = ""
|
|
192
|
+
|
|
193
|
+
unrollpower = unroll.bit_length()-1
|
|
194
|
+
|
|
195
|
+
# Example unroll=4: kleft = k & 0b0111
|
|
196
|
+
asmblock += self.asmwrap(f"and {kleftreg},{kreg},#{unroll-1}")
|
|
197
|
+
# Example unroll=4: k = k >> 2
|
|
198
|
+
asmblock += self.shift(adreg=kreg, bimm=unrollpower, cdreg=kreg, a_dt=_GP, c_dt=_GP, modifiers={_opd3_mod.SHR})
|
|
199
|
+
|
|
200
|
+
return asmblock
|
|
201
|
+
|
|
202
|
+
def kiterkleft(self, *, kreg : greg_base,
|
|
203
|
+
kleftreg : greg_base,
|
|
204
|
+
tmpreg : greg_base,
|
|
205
|
+
unroll : int) -> str:
|
|
206
|
+
|
|
207
|
+
if unroll.bit_count() == 1:
|
|
208
|
+
return self.kiterkleft_pow2(kreg=kreg,kleftreg=kleftreg,unroll=unroll)
|
|
209
|
+
|
|
210
|
+
# TODO: Division by invariant multiplication (the naive attempt below fails,
|
|
211
|
+
# need to read up on it)
|
|
212
|
+
|
|
213
|
+
# runroll = (1<<64) // unroll
|
|
214
|
+
# shift = 64 - unroll.bit_length()
|
|
215
|
+
# asmblock = ""
|
|
216
|
+
|
|
217
|
+
# # Move reciprocal into tmpreg
|
|
218
|
+
# asmblock += self.asmwrap(f"mov {tmpreg}, #{(runroll >> 0) & 0xFFFF}")
|
|
219
|
+
# asmblock += self.asmwrap(f"movk {tmpreg}, #{(runroll >> 16) & 0xFFFF}, lsl 16")
|
|
220
|
+
# asmblock += self.asmwrap(f"movk {tmpreg}, #{(runroll >> 32) & 0xFFFF}, lsl 32")
|
|
221
|
+
# asmblock += self.asmwrap(f"movk {tmpreg}, #{(runroll >> 48) & 0xFFFF}, lsl 48")
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
# # tmp = k // unroll
|
|
225
|
+
# asmblock += self.mul_greg_greg(dst=tmpreg, reg1=kreg, reg2=tmpreg)
|
|
226
|
+
# asmblock += self.shift_greg_right(reg=tmpreg,bit_count=shift)
|
|
227
|
+
#
|
|
228
|
+
# # kleft = k - (tmp * unroll)
|
|
229
|
+
# asmblock += self.mov_greg_imm(reg=kleftreg, imm=unroll)
|
|
230
|
+
# asmblock += self.asmwrap(f"msub {kleftreg},{tmpreg},{kleftreg},{kreg}")
|
|
231
|
+
|
|
232
|
+
# # k = tmp
|
|
233
|
+
# asmblock += self.mov_greg(src=tmpreg,dst=kreg)
|
|
234
|
+
|
|
235
|
+
# return asmblock
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# DIV version
|
|
239
|
+
|
|
240
|
+
asmblock = ""
|
|
241
|
+
|
|
242
|
+
asmblock += self.set(dreg=kleftreg, dt=_GP, modifiers={_opset_mod.CONST}, value=unroll)
|
|
243
|
+
# tmp = k // unroll
|
|
244
|
+
asmblock += self.asmwrap(f"udiv {tmpreg},{kreg},{kleftreg}")
|
|
245
|
+
# kleft = k - (tmp * unroll)
|
|
246
|
+
asmblock += self.asmwrap(f"msub {kleftreg},{tmpreg},{kleftreg},{kreg}")
|
|
247
|
+
# k = tmp
|
|
248
|
+
asmblock += self.move(dregs=[tmpreg, kreg], dts=[_GP, _GP])
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
return asmblock
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def greg(self, reg_idx : int) -> greg_base:
|
|
256
|
+
return aarch64_greg(reg_idx)
|
|
257
|
+
|
|
258
|
+
def freg(self, reg_idx : int, dt : adt) -> freg_base:
|
|
259
|
+
return aarch64_freg(reg_idx=reg_idx, dt=dt)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
6
|
+
"""
|
|
7
|
+
Meta-module for Base AArch64 opmem operations
|
|
8
|
+
"""
|
|
9
|
+
from .load import *
|
|
10
|
+
from .store import *
|
|
11
|
+
from .prefetch import *
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
6
|
+
"""
|
|
7
|
+
Aarch64 opmem operations
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Callable
|
|
11
|
+
|
|
12
|
+
from ...op import (
|
|
13
|
+
opmem,
|
|
14
|
+
opmem_modifier as mod,
|
|
15
|
+
opmem_action,
|
|
16
|
+
operation_signature,
|
|
17
|
+
operand_modifier as opd_mod,
|
|
18
|
+
)
|
|
19
|
+
from ...op.constraint import ValueType
|
|
20
|
+
from ....registers import asm_data_type as adt, adt_size
|
|
21
|
+
|
|
22
|
+
from ..types import aarch64_greg, aarch64_freg
|
|
23
|
+
|
|
24
|
+
from .signatures import make_aarch64_opmem_signatures
|
|
25
|
+
from ...op.opmem import param_signatures
|
|
26
|
+
|
|
27
|
+
class aarch64_opmem(opmem):
|
|
28
|
+
"""
|
|
29
|
+
AArch64 scalar instruction with 1 data operand and 1 address operand.
|
|
30
|
+
Handles standard scalar loads/stores (ldr, str, ldrb, strh, etc.)
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, action: opmem_action,
|
|
34
|
+
asmwrap : Callable[[str],str]):
|
|
35
|
+
self.action = action
|
|
36
|
+
self.asmwrap=asmwrap
|
|
37
|
+
|
|
38
|
+
sigs = make_aarch64_opmem_signatures()
|
|
39
|
+
self.signatures = sigs + param_signatures(sigs)
|
|
40
|
+
|
|
41
|
+
def all_signatures(self) -> list[operation_signature]:
|
|
42
|
+
return self.signatures
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def inst_base(self):
|
|
46
|
+
"""
|
|
47
|
+
Base root for the instruction
|
|
48
|
+
"""
|
|
49
|
+
if self.action == opmem_action.LOAD:
|
|
50
|
+
return "ldr"
|
|
51
|
+
if self.action == opmem_action.STORE:
|
|
52
|
+
return "str"
|
|
53
|
+
raise ValueError(f"Invalid action: {self.action}")
|
|
54
|
+
|
|
55
|
+
# I explicitly want it this way
|
|
56
|
+
# pylint: disable-next=too-many-branches
|
|
57
|
+
def diagnose_failure(self,
|
|
58
|
+
modifiers: set[mod],
|
|
59
|
+
operand_modifiers : dict[str,set[opd_mod]],
|
|
60
|
+
kwargs : dict[str,ValueType],
|
|
61
|
+
dts : dict[str,adt]):
|
|
62
|
+
|
|
63
|
+
if mod.TINDEX in modifiers:
|
|
64
|
+
raise ValueError(
|
|
65
|
+
"Base AArch64 has no ld/st with 2D tile offset indices")
|
|
66
|
+
if mod.VINDEX in modifiers:
|
|
67
|
+
raise ValueError(
|
|
68
|
+
"Base AArch64 has no ld/st with 1D vector offset indices")
|
|
69
|
+
#if mod.GLANE in modifiers:
|
|
70
|
+
# raise ValueError("Base AArch64 has no GP-reg lane ld/st")
|
|
71
|
+
#if mod.ILANE in modifiers:
|
|
72
|
+
# raise ValueError("Base AArch64 has no immediate lane ld/st")
|
|
73
|
+
if mod.TOFFSET in modifiers:
|
|
74
|
+
raise ValueError("Base AArch64 has no ld/st with 2D tile offsets")
|
|
75
|
+
if mod.VOFFSET in modifiers:
|
|
76
|
+
raise ValueError("Base AArch64 has no ld/st with vector offsets")
|
|
77
|
+
if mod.ISTRIDE in modifiers:
|
|
78
|
+
raise ValueError(
|
|
79
|
+
"Base AArch64 has no ld/st with immediate strides")
|
|
80
|
+
if mod.GSTRIDE in modifiers:
|
|
81
|
+
raise ValueError("Base AArch64 has no ld/st with GP-reg strides")
|
|
82
|
+
if mod.STRUCT in modifiers:
|
|
83
|
+
raise ValueError("Base AArch64 has no structured ld/st")
|
|
84
|
+
#if mod.BCAST in modifiers:
|
|
85
|
+
# raise ValueError("Base AArch64 has no broadcasting ld/st")
|
|
86
|
+
if mod.MASK in modifiers:
|
|
87
|
+
raise ValueError("Base AArch64 has no masked ld/st")
|
|
88
|
+
#if mod.ROW in modifiers:
|
|
89
|
+
# raise ValueError("Base AArch64 has no row selection ld/st")
|
|
90
|
+
#if mod.COL in modifiers:
|
|
91
|
+
# raise ValueError("Base AArch64 has no column selection ld/st")
|
|
92
|
+
if mod.NT in modifiers:
|
|
93
|
+
raise NotImplementedError("Non-temporals for Base AArch64 not yet implemented")
|
|
94
|
+
|
|
95
|
+
# `dts` has one entry per passed `dreg`; ld/st always use exactly one
|
|
96
|
+
# register, data-less ops (prefetches) use none
|
|
97
|
+
if self.action in (opmem_action.LOAD, opmem_action.STORE) \
|
|
98
|
+
and len(dts) != 1:
|
|
99
|
+
raise ValueError("AArch64 scalar load/store uses exactly one register.")
|
|
100
|
+
|
|
101
|
+
if mod.POSTINC in modifiers:
|
|
102
|
+
if "iinc" in kwargs and "increg" in kwargs:
|
|
103
|
+
raise ValueError("iinc, increg are mutually exclusive")
|
|
104
|
+
if "iinc" not in kwargs and "increg" not in kwargs:
|
|
105
|
+
raise ValueError("Missing one of these parameters: iinc, increg")
|
|
106
|
+
|
|
107
|
+
if mod.IOFFSET in modifiers and "ioffset" not in kwargs:
|
|
108
|
+
raise ValueError("Missing operand: ioffset")
|
|
109
|
+
|
|
110
|
+
if mod.GOFFSET in modifiers and "offreg" not in kwargs:
|
|
111
|
+
raise ValueError("Missing operand: offreg")
|
|
112
|
+
|
|
113
|
+
def get_addressing(self,
|
|
114
|
+
areg: aarch64_greg,
|
|
115
|
+
modifiers: set[mod], **kwargs) -> str:
|
|
116
|
+
"""
|
|
117
|
+
Constructs the addressing string
|
|
118
|
+
|
|
119
|
+
:param areg: address register
|
|
120
|
+
:param modifiers: operation modifiers
|
|
121
|
+
|
|
122
|
+
:return: string containing the addressing
|
|
123
|
+
"""
|
|
124
|
+
if mod.PARAM in modifiers:
|
|
125
|
+
return f"%[{kwargs['param']}]"
|
|
126
|
+
if not isinstance(areg, aarch64_greg):
|
|
127
|
+
raise ValueError(f"{areg} is not an aarch64_greg")
|
|
128
|
+
|
|
129
|
+
base_addr = f"[{areg}]"
|
|
130
|
+
|
|
131
|
+
if mod.POSTINC in modifiers:
|
|
132
|
+
increg = kwargs.get("increg", None)
|
|
133
|
+
if increg is not None:
|
|
134
|
+
return f"{base_addr}, {increg}"
|
|
135
|
+
|
|
136
|
+
iinc = kwargs["iinc"]
|
|
137
|
+
return f"{base_addr}, #{iinc}"
|
|
138
|
+
|
|
139
|
+
if mod.IOFFSET in modifiers:
|
|
140
|
+
ioffset = kwargs["ioffset"]
|
|
141
|
+
if ioffset == 0:
|
|
142
|
+
return base_addr
|
|
143
|
+
return f"[{areg}, #{ioffset}]"
|
|
144
|
+
|
|
145
|
+
if mod.GOFFSET in modifiers:
|
|
146
|
+
offreg = kwargs["offreg"]
|
|
147
|
+
return f"[{areg}, {offreg}]"
|
|
148
|
+
|
|
149
|
+
return base_addr
|
|
150
|
+
|
|
151
|
+
def get_inst_mnemonic(self, dt: adt, is_freg: bool) -> str:
|
|
152
|
+
"""
|
|
153
|
+
Construct instruction mnemonic
|
|
154
|
+
"""
|
|
155
|
+
base = self.inst_base
|
|
156
|
+
|
|
157
|
+
if is_freg:
|
|
158
|
+
return base
|
|
159
|
+
|
|
160
|
+
size = adt_size(dt)
|
|
161
|
+
if size == 1:
|
|
162
|
+
return base + "b"
|
|
163
|
+
if size == 2:
|
|
164
|
+
return base + "h"
|
|
165
|
+
|
|
166
|
+
return base
|
|
167
|
+
|
|
168
|
+
def implementation(self, *, dregs: list, agreg : aarch64_greg|None = None,
|
|
169
|
+
modifiers: set[mod], **kwargs) -> str:
|
|
170
|
+
|
|
171
|
+
if len(dregs) != 1:
|
|
172
|
+
raise ValueError(
|
|
173
|
+
"AArch64 scalar load/store uses exactly one register.")
|
|
174
|
+
|
|
175
|
+
a_dt = kwargs['a_dt']
|
|
176
|
+
dreg = dregs[0].retype(dt=a_dt)
|
|
177
|
+
is_freg = isinstance(dreg, aarch64_freg)
|
|
178
|
+
|
|
179
|
+
inst = self.get_inst_mnemonic(a_dt, is_freg)
|
|
180
|
+
addressing = self.get_addressing(agreg, modifiers, **kwargs)
|
|
181
|
+
|
|
182
|
+
return self.asmwrap(f"{inst} {dreg}, {addressing}")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
6
|
+
"""
|
|
7
|
+
Base AArch64 load instructions
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Callable
|
|
11
|
+
|
|
12
|
+
from ...op import opmem_action as action
|
|
13
|
+
from .base import aarch64_opmem
|
|
14
|
+
|
|
15
|
+
class aarch64_load(aarch64_opmem):
|
|
16
|
+
"""
|
|
17
|
+
RISC-V freg and greg loads
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, asmwrap : Callable[[str],str]):
|
|
21
|
+
super().__init__(action=action.LOAD, asmwrap=asmwrap)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
6
|
+
"""
|
|
7
|
+
Base AArch64 prefetch instructions
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Callable
|
|
11
|
+
|
|
12
|
+
from ...op import opmem_action as action
|
|
13
|
+
from ...op import opmem_modifier as mod
|
|
14
|
+
from ...op import operand_modifier as opd_mod
|
|
15
|
+
from ..types import aarch64_greg
|
|
16
|
+
from .base import aarch64_opmem
|
|
17
|
+
from .signatures import make_aarch64_prefetch_signatures
|
|
18
|
+
|
|
19
|
+
class aarch64_prefetch(aarch64_opmem):
|
|
20
|
+
"""
|
|
21
|
+
Base AArch64 prefetch (prfm PLDL1KEEP).
|
|
22
|
+
|
|
23
|
+
Data-less opmem (no dregs/dt). Cache level/locality/target selection
|
|
24
|
+
is not exposed yet.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self,
|
|
28
|
+
asmwrap : Callable[[str],str]):
|
|
29
|
+
super().__init__(action=action.PREFETCH, asmwrap=asmwrap)
|
|
30
|
+
self.signatures = make_aarch64_prefetch_signatures()
|
|
31
|
+
|
|
32
|
+
# pylint: disable-next=arguments-differ
|
|
33
|
+
def implementation(self, *, agreg: aarch64_greg,
|
|
34
|
+
modifiers: set[mod],
|
|
35
|
+
operand_modifiers : dict[str,set[opd_mod]],
|
|
36
|
+
**kwargs) -> str:
|
|
37
|
+
del operand_modifiers
|
|
38
|
+
|
|
39
|
+
addressing = self.get_addressing(agreg, modifiers, **kwargs)
|
|
40
|
+
return self.asmwrap(f"prfm PLDL1KEEP, {addressing}")
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
3
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@fz-juelich.de>
|
|
4
|
+
# Copyright (C) 2021 Stepan Nassyr <s.nassyr@xcpp.org>
|
|
5
|
+
# ------------------------------------------------------------------------------
|
|
6
|
+
"""
|
|
7
|
+
Valid signatures for AArch64 opmem operations
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from ....registers import adt_size
|
|
11
|
+
from ...op.constraint import either_constraint, minmax_constraint, multiple_constraint
|
|
12
|
+
from ...op import (
|
|
13
|
+
operation_signature as sig,
|
|
14
|
+
operand_shape as osh,
|
|
15
|
+
operand_type as ot,
|
|
16
|
+
operand_role as orl,
|
|
17
|
+
register_type as rt,
|
|
18
|
+
opmem_modifier as mod
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
from ....registers import asm_data_type as adt, adt_is_float
|
|
22
|
+
|
|
23
|
+
_FLOATS = [adt.FP64, adt.FP32, adt.FP16, adt.FP8E4M3, adt.FP8E5M2]
|
|
24
|
+
_INTS = [adt.SINT64, adt.SINT32, adt.SINT16, adt.SINT8,
|
|
25
|
+
adt.UINT64, adt.UINT32, adt.UINT16, adt.UINT8]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _scale(dt) -> int:
|
|
29
|
+
"""
|
|
30
|
+
What an unsigned immediate offset is scaled by: the access's size - a
|
|
31
|
+
prefetch's (no data) 8, as prfm's
|
|
32
|
+
"""
|
|
33
|
+
return 8 if dt is None else adt_size(dt)
|
|
34
|
+
|
|
35
|
+
def make_aarch64_opmem_signatures():
|
|
36
|
+
"""
|
|
37
|
+
Generate signatures for AArch64 opmem operations
|
|
38
|
+
"""
|
|
39
|
+
sigs = []
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
for dt in _FLOATS+_INTS:
|
|
43
|
+
|
|
44
|
+
a_rt = rt.FP if adt_is_float(dt) else rt.GP
|
|
45
|
+
|
|
46
|
+
# (f)ld without offset
|
|
47
|
+
sigs.append(sig(
|
|
48
|
+
modifiers=set(),
|
|
49
|
+
structural_params={},
|
|
50
|
+
operands={
|
|
51
|
+
'adreg': osh(ot.REGISTER, orl.DATA, a_rt, dt),
|
|
52
|
+
'agreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64)
|
|
53
|
+
}
|
|
54
|
+
))
|
|
55
|
+
# (f)ld with immediate offset
|
|
56
|
+
sigs.append(sig(
|
|
57
|
+
modifiers={mod.IOFFSET},
|
|
58
|
+
structural_params={},
|
|
59
|
+
operands={
|
|
60
|
+
'adreg': osh(ot.REGISTER, orl.DATA, a_rt, dt),
|
|
61
|
+
'agreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64),
|
|
62
|
+
'ioffset': osh(ot.IMMEDIATE, orl.PARAM, None, adt.SINT64, value_constraints=[either_constraint(options=[
|
|
63
|
+
[minmax_constraint(minval=0, maxval=4095*_scale(dt)), multiple_constraint(multiple=_scale(dt))],
|
|
64
|
+
[minmax_constraint(minval=-256, maxval=255)]])])
|
|
65
|
+
}
|
|
66
|
+
))
|
|
67
|
+
# (f)ld with gp-reg offset
|
|
68
|
+
sigs.append(sig(
|
|
69
|
+
modifiers={mod.GOFFSET},
|
|
70
|
+
structural_params={},
|
|
71
|
+
operands={
|
|
72
|
+
'adreg': osh(ot.REGISTER, orl.DATA, a_rt, dt),
|
|
73
|
+
'agreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64),
|
|
74
|
+
'offreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64)
|
|
75
|
+
}
|
|
76
|
+
))
|
|
77
|
+
# (f)ld with postinc immediate offset
|
|
78
|
+
sigs.append(sig(
|
|
79
|
+
modifiers={mod.POSTINC},
|
|
80
|
+
structural_params={},
|
|
81
|
+
operands={
|
|
82
|
+
'adreg': osh(ot.REGISTER, orl.DATA, a_rt, dt),
|
|
83
|
+
'agreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64),
|
|
84
|
+
'iinc': osh(ot.IMMEDIATE, orl.PARAM, None, adt.SINT64, value_constraints=[minmax_constraint(minval=-256, maxval=255)])
|
|
85
|
+
}
|
|
86
|
+
))
|
|
87
|
+
# (f)ld with postinc gp-reg offset
|
|
88
|
+
sigs.append(sig(
|
|
89
|
+
modifiers={mod.POSTINC},
|
|
90
|
+
structural_params={},
|
|
91
|
+
operands={
|
|
92
|
+
'adreg': osh(ot.REGISTER, orl.DATA, a_rt, dt),
|
|
93
|
+
'agreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64),
|
|
94
|
+
'increg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64)
|
|
95
|
+
}
|
|
96
|
+
))
|
|
97
|
+
|
|
98
|
+
return sigs
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def make_aarch64_prefetch_signatures():
|
|
102
|
+
"""
|
|
103
|
+
Generate signatures for AArch64 prefetch operations
|
|
104
|
+
"""
|
|
105
|
+
return [
|
|
106
|
+
# prefetch without offset
|
|
107
|
+
sig(
|
|
108
|
+
modifiers=set(),
|
|
109
|
+
structural_params={},
|
|
110
|
+
operands={
|
|
111
|
+
'agreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64)
|
|
112
|
+
}
|
|
113
|
+
),
|
|
114
|
+
# prefetch with immediate offset
|
|
115
|
+
sig(
|
|
116
|
+
modifiers={mod.IOFFSET},
|
|
117
|
+
structural_params={},
|
|
118
|
+
operands={
|
|
119
|
+
'agreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64),
|
|
120
|
+
'ioffset': osh(ot.IMMEDIATE, orl.PARAM, None, adt.SINT64, value_constraints=[either_constraint(options=[
|
|
121
|
+
[minmax_constraint(minval=0, maxval=4095*_scale(None)), multiple_constraint(multiple=_scale(None))],
|
|
122
|
+
[minmax_constraint(minval=-256, maxval=255)]])])
|
|
123
|
+
}
|
|
124
|
+
),
|
|
125
|
+
# prefetch with gp-reg offset
|
|
126
|
+
sig(
|
|
127
|
+
modifiers={mod.GOFFSET},
|
|
128
|
+
structural_params={},
|
|
129
|
+
operands={
|
|
130
|
+
'agreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64),
|
|
131
|
+
'offreg': osh(ot.REGISTER, orl.ADDRESS, rt.GP, adt.UINT64)
|
|
132
|
+
}
|
|
133
|
+
),
|
|
134
|
+
]
|