PyNerva 0.0.5__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.
Potentially problematic release.
This version of PyNerva might be problematic. Click here for more details.
- nervapy/__init__.py +50 -0
- nervapy/abi.py +91 -0
- nervapy/arm/__init__.py +124 -0
- nervapy/arm/__main__.py +0 -0
- nervapy/arm/abi.py +138 -0
- nervapy/arm/formats.py +49 -0
- nervapy/arm/function.py +2405 -0
- nervapy/arm/generic.py +10797 -0
- nervapy/arm/instructions.py +519 -0
- nervapy/arm/isa.py +409 -0
- nervapy/arm/literal_pool.py +331 -0
- nervapy/arm/microarchitecture.py +211 -0
- nervapy/arm/pseudo.py +652 -0
- nervapy/arm/registers.py +1458 -0
- nervapy/arm/vfpneon.py +4092 -0
- nervapy/arm.py +13 -0
- nervapy/c/__init__.py +1 -0
- nervapy/c/types.py +436 -0
- nervapy/codegen.py +99 -0
- nervapy/common/__init__.py +4 -0
- nervapy/common/function.py +5 -0
- nervapy/common/regalloc.py +121 -0
- nervapy/constant_data.py +282 -0
- nervapy/encoder.py +246 -0
- nervapy/formats/__init__.py +2 -0
- nervapy/formats/elf/__init__.py +4 -0
- nervapy/formats/elf/file.py +178 -0
- nervapy/formats/elf/image.py +106 -0
- nervapy/formats/elf/section.py +422 -0
- nervapy/formats/elf/symbol.py +281 -0
- nervapy/formats/macho/__init__.py +2 -0
- nervapy/formats/macho/file.py +123 -0
- nervapy/formats/macho/image.py +143 -0
- nervapy/formats/macho/section.py +322 -0
- nervapy/formats/macho/symbol.py +158 -0
- nervapy/formats/mscoff/__init__.py +8 -0
- nervapy/formats/mscoff/image.py +132 -0
- nervapy/formats/mscoff/section.py +181 -0
- nervapy/formats/mscoff/symbol.py +148 -0
- nervapy/function.py +136 -0
- nervapy/literal.py +731 -0
- nervapy/loader.py +188 -0
- nervapy/name.py +159 -0
- nervapy/parse.py +52 -0
- nervapy/stream.py +58 -0
- nervapy/util.py +126 -0
- nervapy/writer.py +518 -0
- nervapy/x86_64/__init__.py +324 -0
- nervapy/x86_64/__main__.py +407 -0
- nervapy/x86_64/abi.py +517 -0
- nervapy/x86_64/amd.py +6464 -0
- nervapy/x86_64/avx.py +102029 -0
- nervapy/x86_64/crypto.py +1533 -0
- nervapy/x86_64/encoding.py +424 -0
- nervapy/x86_64/fma.py +19138 -0
- nervapy/x86_64/function.py +2707 -0
- nervapy/x86_64/generic.py +23384 -0
- nervapy/x86_64/instructions.py +500 -0
- nervapy/x86_64/isa.py +476 -0
- nervapy/x86_64/lower.py +126 -0
- nervapy/x86_64/mask.py +2593 -0
- nervapy/x86_64/meta.py +143 -0
- nervapy/x86_64/mmxsse.py +17265 -0
- nervapy/x86_64/nacl.py +327 -0
- nervapy/x86_64/operand.py +1204 -0
- nervapy/x86_64/options.py +21 -0
- nervapy/x86_64/pseudo.py +686 -0
- nervapy/x86_64/registers.py +1225 -0
- nervapy/x86_64/types.py +17 -0
- nervapy/x86_64/uarch.py +580 -0
- pynerva-0.0.5.dist-info/METADATA +310 -0
- pynerva-0.0.5.dist-info/RECORD +74 -0
- pynerva-0.0.5.dist-info/WHEEL +4 -0
- pynerva-0.0.5.dist-info/licenses/LICENSE.rst +15 -0
|
@@ -0,0 +1,1225 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
from typing import Any, ClassVar, Dict, Optional
|
|
6
|
+
|
|
7
|
+
import six
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Register(object):
|
|
11
|
+
"""A base class for all encodable registers (rip is not encodable)"""
|
|
12
|
+
|
|
13
|
+
_mask_size_map = {
|
|
14
|
+
0x1: 1,
|
|
15
|
+
0x2: 1,
|
|
16
|
+
0x3: 2,
|
|
17
|
+
0x7: 4,
|
|
18
|
+
0xF: 8,
|
|
19
|
+
0x10: 8,
|
|
20
|
+
0x40: 8,
|
|
21
|
+
0x100: 16,
|
|
22
|
+
0x300: 32,
|
|
23
|
+
0x700: 64,
|
|
24
|
+
}
|
|
25
|
+
size: Optional[int] = None
|
|
26
|
+
|
|
27
|
+
def __init__(self, mask, virtual_id=None, physical_id=None):
|
|
28
|
+
super(Register, self).__init__()
|
|
29
|
+
from nervapy.util import is_int
|
|
30
|
+
|
|
31
|
+
assert is_int(mask), "Mask must be an integer"
|
|
32
|
+
assert mask in Register._mask_size_map, "Unknown mask value: %X" % mask
|
|
33
|
+
self.mask = int(mask)
|
|
34
|
+
assert (
|
|
35
|
+
virtual_id is not None or physical_id is not None
|
|
36
|
+
), "Virtual or physical ID must be specified"
|
|
37
|
+
assert (
|
|
38
|
+
virtual_id is None or is_int(virtual_id) and virtual_id > 0
|
|
39
|
+
), "Virtual ID must be a positive integer"
|
|
40
|
+
assert (
|
|
41
|
+
physical_id is None or is_int(physical_id) and physical_id >= 0
|
|
42
|
+
), "Physical ID must be a non-negative integer"
|
|
43
|
+
self.virtual_id = None if virtual_id is None else int(virtual_id)
|
|
44
|
+
self.physical_id = None if physical_id is None else int(physical_id)
|
|
45
|
+
|
|
46
|
+
def __eq__(self, other):
|
|
47
|
+
return (
|
|
48
|
+
isinstance(other, Register)
|
|
49
|
+
and self.mask == other.mask
|
|
50
|
+
and self._internal_id == other._internal_id
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def __ne__(self, other):
|
|
54
|
+
return (
|
|
55
|
+
not isinstance(other, Register)
|
|
56
|
+
or self.mask != other.mask
|
|
57
|
+
or self._internal_id != other._internal_id
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def __lt__(self, other):
|
|
61
|
+
return isinstance(other, Register) and (self.mask, -self._internal_id) < (
|
|
62
|
+
other.mask,
|
|
63
|
+
-other._internal_id,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def __le__(self, other):
|
|
67
|
+
return isinstance(other, Register) and (self.mask, -self._internal_id) <= (
|
|
68
|
+
other.mask,
|
|
69
|
+
-other._internal_id,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def __hash__(self):
|
|
73
|
+
h = hash(self.mask)
|
|
74
|
+
if self.physical_id is not None:
|
|
75
|
+
return hash(self.physical_id) ^ h
|
|
76
|
+
else:
|
|
77
|
+
return hash(self.virtual_id) ^ h
|
|
78
|
+
|
|
79
|
+
def __repr__(self):
|
|
80
|
+
return str(self)
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def _internal_id(self):
|
|
84
|
+
if self.is_virtual:
|
|
85
|
+
return -self.virtual_id
|
|
86
|
+
else:
|
|
87
|
+
return self.physical_id
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def _reconstruct(internal_id, mask):
|
|
91
|
+
registers = set()
|
|
92
|
+
if internal_id >= 0:
|
|
93
|
+
# Physical register
|
|
94
|
+
if mask & 0x400 != 0:
|
|
95
|
+
mask &= ~0x700
|
|
96
|
+
registers.add(ZMMRegister(physical_id=internal_id))
|
|
97
|
+
elif mask & 0x200 != 0:
|
|
98
|
+
mask &= ~0x300
|
|
99
|
+
registers.add(YMMRegister(physical_id=internal_id))
|
|
100
|
+
elif mask & 0x100 != 0:
|
|
101
|
+
mask &= ~0x100
|
|
102
|
+
registers.add(XMMRegister(physical_id=internal_id))
|
|
103
|
+
if mask & 0x10 != 0:
|
|
104
|
+
mask &= ~0x10
|
|
105
|
+
registers.add(MMXRegister(physical_id=internal_id))
|
|
106
|
+
if mask & 0x8 != 0:
|
|
107
|
+
mask &= ~0xF
|
|
108
|
+
registers.add(GeneralPurposeRegister64(physical_id=internal_id))
|
|
109
|
+
elif mask & 0x4 != 0:
|
|
110
|
+
mask &= ~0x7
|
|
111
|
+
registers.add(GeneralPurposeRegister32(physical_id=internal_id))
|
|
112
|
+
elif mask & 0x2 != 0:
|
|
113
|
+
mask &= ~0x3
|
|
114
|
+
registers.add(GeneralPurposeRegister16(physical_id=internal_id))
|
|
115
|
+
elif mask & 0x1 != 0:
|
|
116
|
+
mask &= ~0x1
|
|
117
|
+
registers.add(GeneralPurposeRegister8(physical_id=internal_id))
|
|
118
|
+
assert mask == 0, "Unknown register mask component: %X" % mask
|
|
119
|
+
else:
|
|
120
|
+
# Virtual register
|
|
121
|
+
# Physical register
|
|
122
|
+
if mask & 0x400 != 0:
|
|
123
|
+
mask &= ~0x700
|
|
124
|
+
registers.add(ZMMRegister(virtual_id=-internal_id))
|
|
125
|
+
elif mask & 0x200 != 0:
|
|
126
|
+
mask &= ~0x300
|
|
127
|
+
registers.add(YMMRegister(virtual_id=-internal_id))
|
|
128
|
+
elif mask & 0x100 != 0:
|
|
129
|
+
mask &= ~0x100
|
|
130
|
+
registers.add(XMMRegister(virtual_id=-internal_id))
|
|
131
|
+
if mask & 0x10 != 0:
|
|
132
|
+
mask &= ~0x10
|
|
133
|
+
registers.add(MMXRegister(virtual_id=-internal_id))
|
|
134
|
+
if mask & 0x40 != 0:
|
|
135
|
+
mask &= ~0x40
|
|
136
|
+
registers.add(KRegister(virtual_id=-internal_id))
|
|
137
|
+
if mask & 0x8 != 0:
|
|
138
|
+
mask &= ~0xF
|
|
139
|
+
registers.add(GeneralPurposeRegister64(virtual_id=-internal_id))
|
|
140
|
+
elif mask & 0x4 != 0:
|
|
141
|
+
mask &= ~0x7
|
|
142
|
+
registers.add(GeneralPurposeRegister32(virtual_id=-internal_id))
|
|
143
|
+
elif mask & 0x2 != 0:
|
|
144
|
+
mask &= ~0x3
|
|
145
|
+
registers.add(GeneralPurposeRegister16(virtual_id=-internal_id))
|
|
146
|
+
elif mask & 0x1 != 0:
|
|
147
|
+
mask &= ~0x1
|
|
148
|
+
registers.add(GeneralPurposeRegister8(virtual_id=-internal_id))
|
|
149
|
+
assert mask == 0, "Unknown register mask component: %X" % mask
|
|
150
|
+
return registers
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
def _reconstruct_multiple(reg_dict):
|
|
154
|
+
reg_set = set()
|
|
155
|
+
for reg_id, reg_mask in six.iteritems(reg_dict):
|
|
156
|
+
reg_set.update(Register._reconstruct(reg_id, reg_mask))
|
|
157
|
+
return reg_set
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def kind(self):
|
|
161
|
+
if self.mask & GeneralPurposeRegister64._mask != 0:
|
|
162
|
+
return GeneralPurposeRegister._kind
|
|
163
|
+
elif self.mask & MMXRegister._mask != 0:
|
|
164
|
+
return MMXRegister._kind
|
|
165
|
+
elif self.mask & XMMRegister._mask != 0:
|
|
166
|
+
return XMMRegister._kind
|
|
167
|
+
elif self.mask & KRegister._mask != 0:
|
|
168
|
+
return KRegister._kind
|
|
169
|
+
else:
|
|
170
|
+
assert False, "Unknown register mask: %X" % self.mask
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def is_virtual(self):
|
|
174
|
+
"""Indicated if a register is virtual, i.e. not bounded to a physical register"""
|
|
175
|
+
return self.physical_id is None
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def lcode(self):
|
|
179
|
+
"""Returns the bits 0-2 of register encoding"""
|
|
180
|
+
assert (
|
|
181
|
+
self.physical_id is not None
|
|
182
|
+
), "The method returns encoding detail for a physical register"
|
|
183
|
+
if self.mask == GeneralPurposeRegister8._high_mask:
|
|
184
|
+
assert (
|
|
185
|
+
self.physical_id & ~0x3 == 0
|
|
186
|
+
), "Only ah, bh, ch, dh can be the high 8-bit registers"
|
|
187
|
+
return 0x4 | self.physical_id
|
|
188
|
+
else:
|
|
189
|
+
return self.physical_id & 0x7
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def hcode(self):
|
|
193
|
+
"""Returns the bit 3 of register encoding"""
|
|
194
|
+
assert (
|
|
195
|
+
self.physical_id is not None
|
|
196
|
+
), "The method returns encoding detail for a physical register"
|
|
197
|
+
return (self.physical_id >> 3) & 1
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def ecode(self):
|
|
201
|
+
"""Returns the bit 4 of register encoding"""
|
|
202
|
+
assert (
|
|
203
|
+
self.physical_id is not None
|
|
204
|
+
), "The method returns encoding detail for a physical register"
|
|
205
|
+
return (self.physical_id >> 4) & 1
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def hlcode(self):
|
|
209
|
+
"""Returns the bits 0-3 of register encoding"""
|
|
210
|
+
assert (
|
|
211
|
+
self.physical_id is not None
|
|
212
|
+
), "The method returns encoding detail for a physical register"
|
|
213
|
+
assert (
|
|
214
|
+
self.mask != GeneralPurposeRegister8._high_mask
|
|
215
|
+
), "ah/bh/ch/dh registers never use 4-bit encoding"
|
|
216
|
+
return self.physical_id & 0xF
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def ehcode(self):
|
|
220
|
+
"""Returns the bits 3-4 of register encoding"""
|
|
221
|
+
assert (
|
|
222
|
+
self.physical_id is not None
|
|
223
|
+
), "The method returns encoding detail for a physical register"
|
|
224
|
+
return (self.physical_id >> 3) & 0b11
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class GeneralPurposeRegister(Register):
|
|
228
|
+
"""A base class for general-purpose registers"""
|
|
229
|
+
|
|
230
|
+
_go_physical_id_map: ClassVar[Dict[Any, str]] = {
|
|
231
|
+
0x0: "AX",
|
|
232
|
+
0x1: "CX",
|
|
233
|
+
0x2: "DX",
|
|
234
|
+
0x3: "BX",
|
|
235
|
+
0x4: "SP",
|
|
236
|
+
0x5: "BP",
|
|
237
|
+
0x6: "SI",
|
|
238
|
+
0x7: "DI",
|
|
239
|
+
0x8: "R8",
|
|
240
|
+
0x9: "R9",
|
|
241
|
+
0xA: "R10",
|
|
242
|
+
0xB: "R11",
|
|
243
|
+
0xC: "R12",
|
|
244
|
+
0xD: "R13",
|
|
245
|
+
0xE: "R14",
|
|
246
|
+
0xF: "R15",
|
|
247
|
+
}
|
|
248
|
+
_kind = 1
|
|
249
|
+
|
|
250
|
+
def __init__(self, mask, virtual_id=None, physical_id=None):
|
|
251
|
+
super(GeneralPurposeRegister, self).__init__(mask, virtual_id, physical_id)
|
|
252
|
+
|
|
253
|
+
@property
|
|
254
|
+
def as_low_byte(self):
|
|
255
|
+
return GeneralPurposeRegister8(self.physical_id, self.virtual_id)
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def as_word(self):
|
|
259
|
+
return GeneralPurposeRegister16(self.physical_id, self.virtual_id)
|
|
260
|
+
|
|
261
|
+
@property
|
|
262
|
+
def as_dword(self):
|
|
263
|
+
return GeneralPurposeRegister32(self.physical_id, self.virtual_id)
|
|
264
|
+
|
|
265
|
+
@property
|
|
266
|
+
def as_qword(self):
|
|
267
|
+
return GeneralPurposeRegister64(self.physical_id, self.virtual_id)
|
|
268
|
+
|
|
269
|
+
def format(self, assembly_format):
|
|
270
|
+
assert assembly_format in {
|
|
271
|
+
"peachpy",
|
|
272
|
+
"gas",
|
|
273
|
+
"nasm",
|
|
274
|
+
"go",
|
|
275
|
+
}, "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
|
|
276
|
+
|
|
277
|
+
if assembly_format == "go":
|
|
278
|
+
assert (
|
|
279
|
+
not self.is_virtual
|
|
280
|
+
), "Go assembler does not support virtual registers"
|
|
281
|
+
return GeneralPurposeRegister._go_physical_id_map[self.physical_id]
|
|
282
|
+
elif assembly_format == "gas":
|
|
283
|
+
return "%" + str(self)
|
|
284
|
+
else:
|
|
285
|
+
return str(self)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class GeneralPurposeRegister64(GeneralPurposeRegister):
|
|
289
|
+
"""64-bit general-purpose register"""
|
|
290
|
+
|
|
291
|
+
size = 8
|
|
292
|
+
|
|
293
|
+
_physical_id_map = {
|
|
294
|
+
0x0: "rax",
|
|
295
|
+
0x1: "rcx",
|
|
296
|
+
0x2: "rdx",
|
|
297
|
+
0x3: "rbx",
|
|
298
|
+
0x4: "rsp",
|
|
299
|
+
0x5: "rbp",
|
|
300
|
+
0x6: "rsi",
|
|
301
|
+
0x7: "rdi",
|
|
302
|
+
0x8: "r8",
|
|
303
|
+
0x9: "r9",
|
|
304
|
+
0xA: "r10",
|
|
305
|
+
0xB: "r11",
|
|
306
|
+
0xC: "r12",
|
|
307
|
+
0xD: "r13",
|
|
308
|
+
0xE: "r14",
|
|
309
|
+
0xF: "r15",
|
|
310
|
+
}
|
|
311
|
+
_mask = 0xF
|
|
312
|
+
|
|
313
|
+
def __init__(self, physical_id=None, virtual_id=None):
|
|
314
|
+
if virtual_id is None and physical_id is None:
|
|
315
|
+
from nervapy.common.function import active_function
|
|
316
|
+
|
|
317
|
+
super(GeneralPurposeRegister64, self).__init__(
|
|
318
|
+
GeneralPurposeRegister64._mask,
|
|
319
|
+
active_function._allocate_general_purpose_register_id(),
|
|
320
|
+
)
|
|
321
|
+
else:
|
|
322
|
+
super(GeneralPurposeRegister64, self).__init__(
|
|
323
|
+
GeneralPurposeRegister64._mask, virtual_id, physical_id
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
def __str__(self):
|
|
327
|
+
if self.is_virtual:
|
|
328
|
+
return "gp64-vreg<%d>" % self.virtual_id
|
|
329
|
+
else:
|
|
330
|
+
return GeneralPurposeRegister64._physical_id_map[self.physical_id]
|
|
331
|
+
|
|
332
|
+
def __add__(self, offset):
|
|
333
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
334
|
+
|
|
335
|
+
return MemoryAddress(self) + offset
|
|
336
|
+
|
|
337
|
+
def __sub__(self, offset):
|
|
338
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
339
|
+
|
|
340
|
+
return MemoryAddress(self) - offset
|
|
341
|
+
|
|
342
|
+
def __mul__(self, scale):
|
|
343
|
+
from nervapy.util import is_int
|
|
344
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
345
|
+
|
|
346
|
+
if not is_int(scale):
|
|
347
|
+
raise TypeError("Register can be scaled only by an integer number")
|
|
348
|
+
if int(scale) not in {1, 2, 4, 8}:
|
|
349
|
+
raise ValueError(
|
|
350
|
+
"Invalid scale value (%d): only scaling by 1, 2, 4, or 8 is supported"
|
|
351
|
+
% scale
|
|
352
|
+
)
|
|
353
|
+
return MemoryAddress(index=self, scale=scale)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
rax = GeneralPurposeRegister64(0)
|
|
357
|
+
rcx = GeneralPurposeRegister64(1)
|
|
358
|
+
rdx = GeneralPurposeRegister64(2)
|
|
359
|
+
rbx = GeneralPurposeRegister64(3)
|
|
360
|
+
rsp = GeneralPurposeRegister64(4)
|
|
361
|
+
rbp = GeneralPurposeRegister64(5)
|
|
362
|
+
rsi = GeneralPurposeRegister64(6)
|
|
363
|
+
rdi = GeneralPurposeRegister64(7)
|
|
364
|
+
r8 = GeneralPurposeRegister64(8)
|
|
365
|
+
r9 = GeneralPurposeRegister64(9)
|
|
366
|
+
r10 = GeneralPurposeRegister64(10)
|
|
367
|
+
r11 = GeneralPurposeRegister64(11)
|
|
368
|
+
r12 = GeneralPurposeRegister64(12)
|
|
369
|
+
r13 = GeneralPurposeRegister64(13)
|
|
370
|
+
r14 = GeneralPurposeRegister64(14)
|
|
371
|
+
r15 = GeneralPurposeRegister64(15)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class GeneralPurposeRegister32(GeneralPurposeRegister):
|
|
375
|
+
"""32-bit general-purpose register"""
|
|
376
|
+
|
|
377
|
+
size = 4
|
|
378
|
+
|
|
379
|
+
_physical_id_map = {
|
|
380
|
+
0x0: "eax",
|
|
381
|
+
0x1: "ecx",
|
|
382
|
+
0x2: "edx",
|
|
383
|
+
0x3: "ebx",
|
|
384
|
+
0x4: "esp",
|
|
385
|
+
0x5: "ebp",
|
|
386
|
+
0x6: "esi",
|
|
387
|
+
0x7: "edi",
|
|
388
|
+
0x8: "r8d",
|
|
389
|
+
0x9: "r9d",
|
|
390
|
+
0xA: "r10d",
|
|
391
|
+
0xB: "r11d",
|
|
392
|
+
0xC: "r12d",
|
|
393
|
+
0xD: "r13d",
|
|
394
|
+
0xE: "r14d",
|
|
395
|
+
0xF: "r15d",
|
|
396
|
+
}
|
|
397
|
+
_mask = 0x7
|
|
398
|
+
|
|
399
|
+
def __init__(self, physical_id=None, virtual_id=None):
|
|
400
|
+
if virtual_id is None and physical_id is None:
|
|
401
|
+
from nervapy.common.function import active_function
|
|
402
|
+
|
|
403
|
+
super(GeneralPurposeRegister32, self).__init__(
|
|
404
|
+
GeneralPurposeRegister32._mask,
|
|
405
|
+
active_function._allocate_general_purpose_register_id(),
|
|
406
|
+
)
|
|
407
|
+
else:
|
|
408
|
+
super(GeneralPurposeRegister32, self).__init__(
|
|
409
|
+
GeneralPurposeRegister32._mask, virtual_id, physical_id
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
def __str__(self):
|
|
413
|
+
if self.is_virtual:
|
|
414
|
+
return "gp32-vreg<%d>" % self.virtual_id
|
|
415
|
+
else:
|
|
416
|
+
return GeneralPurposeRegister32._physical_id_map[self.physical_id]
|
|
417
|
+
|
|
418
|
+
def __add__(self, offset):
|
|
419
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
420
|
+
|
|
421
|
+
return MemoryAddress(self) + offset
|
|
422
|
+
|
|
423
|
+
def __sub__(self, offset):
|
|
424
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
425
|
+
|
|
426
|
+
return MemoryAddress(self) - offset
|
|
427
|
+
|
|
428
|
+
def __mul__(self, scale):
|
|
429
|
+
from nervapy.util import is_int
|
|
430
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
431
|
+
|
|
432
|
+
if not is_int(scale):
|
|
433
|
+
raise TypeError("Register can be scaled only by an integer number")
|
|
434
|
+
if int(scale) not in {1, 2, 4, 8}:
|
|
435
|
+
raise ValueError(
|
|
436
|
+
"Invalid scale value (%d): only scaling by 1, 2, 4, or 8 is supported"
|
|
437
|
+
% scale
|
|
438
|
+
)
|
|
439
|
+
return MemoryAddress(index=self, scale=scale)
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
eax = GeneralPurposeRegister32(0)
|
|
443
|
+
ecx = GeneralPurposeRegister32(1)
|
|
444
|
+
edx = GeneralPurposeRegister32(2)
|
|
445
|
+
ebx = GeneralPurposeRegister32(3)
|
|
446
|
+
esp = GeneralPurposeRegister32(4)
|
|
447
|
+
ebp = GeneralPurposeRegister32(5)
|
|
448
|
+
esi = GeneralPurposeRegister32(6)
|
|
449
|
+
edi = GeneralPurposeRegister32(7)
|
|
450
|
+
r8d = GeneralPurposeRegister32(8)
|
|
451
|
+
r9d = GeneralPurposeRegister32(9)
|
|
452
|
+
r10d = GeneralPurposeRegister32(10)
|
|
453
|
+
r11d = GeneralPurposeRegister32(11)
|
|
454
|
+
r12d = GeneralPurposeRegister32(12)
|
|
455
|
+
r13d = GeneralPurposeRegister32(13)
|
|
456
|
+
r14d = GeneralPurposeRegister32(14)
|
|
457
|
+
r15d = GeneralPurposeRegister32(15)
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
class GeneralPurposeRegister16(GeneralPurposeRegister):
|
|
461
|
+
"""16-bit general-purpose register"""
|
|
462
|
+
|
|
463
|
+
size = 2
|
|
464
|
+
|
|
465
|
+
_physical_id_map = {
|
|
466
|
+
0x0: "ax",
|
|
467
|
+
0x1: "cx",
|
|
468
|
+
0x2: "dx",
|
|
469
|
+
0x3: "bx",
|
|
470
|
+
0x4: "sp",
|
|
471
|
+
0x5: "bp",
|
|
472
|
+
0x6: "si",
|
|
473
|
+
0x7: "di",
|
|
474
|
+
0x8: "r8w",
|
|
475
|
+
0x9: "r9w",
|
|
476
|
+
0xA: "r10w",
|
|
477
|
+
0xB: "r11w",
|
|
478
|
+
0xC: "r12w",
|
|
479
|
+
0xD: "r13w",
|
|
480
|
+
0xE: "r14w",
|
|
481
|
+
0xF: "r15w",
|
|
482
|
+
}
|
|
483
|
+
_mask = 0x3
|
|
484
|
+
|
|
485
|
+
def __init__(self, physical_id=None, virtual_id=None):
|
|
486
|
+
if virtual_id is None and physical_id is None:
|
|
487
|
+
from nervapy.common.function import active_function
|
|
488
|
+
|
|
489
|
+
super(GeneralPurposeRegister16, self).__init__(
|
|
490
|
+
GeneralPurposeRegister16._mask,
|
|
491
|
+
active_function._allocate_general_purpose_register_id(),
|
|
492
|
+
)
|
|
493
|
+
else:
|
|
494
|
+
super(GeneralPurposeRegister16, self).__init__(
|
|
495
|
+
GeneralPurposeRegister16._mask, virtual_id, physical_id
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
def __str__(self):
|
|
499
|
+
if self.is_virtual:
|
|
500
|
+
return "gp16-vreg<%d>" % self.virtual_id
|
|
501
|
+
else:
|
|
502
|
+
return GeneralPurposeRegister16._physical_id_map[self.physical_id]
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
ax = GeneralPurposeRegister16(0)
|
|
506
|
+
cx = GeneralPurposeRegister16(1)
|
|
507
|
+
dx = GeneralPurposeRegister16(2)
|
|
508
|
+
bx = GeneralPurposeRegister16(3)
|
|
509
|
+
sp = GeneralPurposeRegister16(4)
|
|
510
|
+
bp = GeneralPurposeRegister16(5)
|
|
511
|
+
si = GeneralPurposeRegister16(6)
|
|
512
|
+
di = GeneralPurposeRegister16(7)
|
|
513
|
+
r8w = GeneralPurposeRegister16(8)
|
|
514
|
+
r9w = GeneralPurposeRegister16(9)
|
|
515
|
+
r10w = GeneralPurposeRegister16(10)
|
|
516
|
+
r11w = GeneralPurposeRegister16(11)
|
|
517
|
+
r12w = GeneralPurposeRegister16(12)
|
|
518
|
+
r13w = GeneralPurposeRegister16(13)
|
|
519
|
+
r14w = GeneralPurposeRegister16(14)
|
|
520
|
+
r15w = GeneralPurposeRegister16(15)
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
class GeneralPurposeRegister8(GeneralPurposeRegister):
|
|
524
|
+
"""8-bit general-purpose register"""
|
|
525
|
+
|
|
526
|
+
size = 1
|
|
527
|
+
|
|
528
|
+
_physical_id_map = {
|
|
529
|
+
(0x0, 0x1): "al",
|
|
530
|
+
(0x1, 0x1): "cl",
|
|
531
|
+
(0x2, 0x1): "dl",
|
|
532
|
+
(0x3, 0x1): "bl",
|
|
533
|
+
(0x0, 0x2): "ah",
|
|
534
|
+
(0x1, 0x2): "ch",
|
|
535
|
+
(0x2, 0x2): "dh",
|
|
536
|
+
(0x3, 0x2): "bh",
|
|
537
|
+
(0x4, 0x1): "spl",
|
|
538
|
+
(0x5, 0x1): "bpl",
|
|
539
|
+
(0x6, 0x1): "sil",
|
|
540
|
+
(0x7, 0x1): "dil",
|
|
541
|
+
(0x8, 0x1): "r8b",
|
|
542
|
+
(0x9, 0x1): "r9b",
|
|
543
|
+
(0xA, 0x1): "r10b",
|
|
544
|
+
(0xB, 0x1): "r11b",
|
|
545
|
+
(0xC, 0x1): "r12b",
|
|
546
|
+
(0xD, 0x1): "r13b",
|
|
547
|
+
(0xE, 0x1): "r14b",
|
|
548
|
+
(0xF, 0x1): "r15b",
|
|
549
|
+
}
|
|
550
|
+
_go_physical_id_map = {
|
|
551
|
+
(0x0, 0x1): "AX",
|
|
552
|
+
(0x1, 0x1): "CX",
|
|
553
|
+
(0x2, 0x1): "DX",
|
|
554
|
+
(0x3, 0x1): "BX",
|
|
555
|
+
(0x0, 0x2): "AH",
|
|
556
|
+
(0x1, 0x2): "CH",
|
|
557
|
+
(0x2, 0x2): "DH",
|
|
558
|
+
(0x3, 0x2): "BH",
|
|
559
|
+
(0x4, 0x1): "SP",
|
|
560
|
+
(0x5, 0x1): "BP",
|
|
561
|
+
(0x6, 0x1): "SI",
|
|
562
|
+
(0x7, 0x1): "DI",
|
|
563
|
+
(0x8, 0x1): "R8",
|
|
564
|
+
(0x9, 0x1): "R9",
|
|
565
|
+
(0xA, 0x1): "R10",
|
|
566
|
+
(0xB, 0x1): "R11",
|
|
567
|
+
(0xC, 0x1): "R12",
|
|
568
|
+
(0xD, 0x1): "R13",
|
|
569
|
+
(0xE, 0x1): "R14",
|
|
570
|
+
(0xF, 0x1): "R15",
|
|
571
|
+
}
|
|
572
|
+
_mask = 0x1
|
|
573
|
+
_high_mask = 0x2
|
|
574
|
+
|
|
575
|
+
def __init__(self, physical_id=None, virtual_id=None, is_high=False):
|
|
576
|
+
mask = (
|
|
577
|
+
GeneralPurposeRegister8._high_mask
|
|
578
|
+
if is_high
|
|
579
|
+
else GeneralPurposeRegister8._mask
|
|
580
|
+
)
|
|
581
|
+
if virtual_id is None and physical_id is None:
|
|
582
|
+
from nervapy.common.function import active_function
|
|
583
|
+
|
|
584
|
+
super(GeneralPurposeRegister8, self).__init__(
|
|
585
|
+
mask, active_function._allocate_general_purpose_register_id()
|
|
586
|
+
)
|
|
587
|
+
else:
|
|
588
|
+
super(GeneralPurposeRegister8, self).__init__(mask, virtual_id, physical_id)
|
|
589
|
+
|
|
590
|
+
def __str__(self):
|
|
591
|
+
if self.is_virtual:
|
|
592
|
+
return "gp8-vreg<%d>" % self.virtual_id
|
|
593
|
+
else:
|
|
594
|
+
return GeneralPurposeRegister8._physical_id_map[
|
|
595
|
+
(self.physical_id, self.mask)
|
|
596
|
+
]
|
|
597
|
+
|
|
598
|
+
def format(self, assembly_format):
|
|
599
|
+
assert assembly_format in {
|
|
600
|
+
"peachpy",
|
|
601
|
+
"gas",
|
|
602
|
+
"nasm",
|
|
603
|
+
"go",
|
|
604
|
+
}, "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
|
|
605
|
+
|
|
606
|
+
if assembly_format == "go":
|
|
607
|
+
assert (
|
|
608
|
+
not self.is_virtual
|
|
609
|
+
), "Go assembler does not support virtual registers"
|
|
610
|
+
return GeneralPurposeRegister8._go_physical_id_map[
|
|
611
|
+
(self.physical_id, self.mask)
|
|
612
|
+
]
|
|
613
|
+
else:
|
|
614
|
+
return super(GeneralPurposeRegister8, self).format(assembly_format)
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
al = GeneralPurposeRegister8(0)
|
|
618
|
+
cl = GeneralPurposeRegister8(1)
|
|
619
|
+
dl = GeneralPurposeRegister8(2)
|
|
620
|
+
bl = GeneralPurposeRegister8(3)
|
|
621
|
+
ah = GeneralPurposeRegister8(0, is_high=True)
|
|
622
|
+
ch = GeneralPurposeRegister8(1, is_high=True)
|
|
623
|
+
dh = GeneralPurposeRegister8(2, is_high=True)
|
|
624
|
+
bh = GeneralPurposeRegister8(3, is_high=True)
|
|
625
|
+
spl = GeneralPurposeRegister8(4)
|
|
626
|
+
bpl = GeneralPurposeRegister8(5)
|
|
627
|
+
sil = GeneralPurposeRegister8(6)
|
|
628
|
+
dil = GeneralPurposeRegister8(7)
|
|
629
|
+
r8b = GeneralPurposeRegister8(8)
|
|
630
|
+
r9b = GeneralPurposeRegister8(9)
|
|
631
|
+
r10b = GeneralPurposeRegister8(10)
|
|
632
|
+
r11b = GeneralPurposeRegister8(11)
|
|
633
|
+
r12b = GeneralPurposeRegister8(12)
|
|
634
|
+
r13b = GeneralPurposeRegister8(13)
|
|
635
|
+
r14b = GeneralPurposeRegister8(14)
|
|
636
|
+
r15b = GeneralPurposeRegister8(15)
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
class MMXRegister(Register):
|
|
640
|
+
"""64-bit MMX technology register"""
|
|
641
|
+
|
|
642
|
+
size = 8
|
|
643
|
+
|
|
644
|
+
_physical_id_map = {n: "mm" + str(n) for n in range(8)}
|
|
645
|
+
_go_physical_id_map = {n: "M" + str(n) for n in range(8)}
|
|
646
|
+
_kind = 2
|
|
647
|
+
_mask = 0x10
|
|
648
|
+
|
|
649
|
+
def __init__(self, physical_id=None, virtual_id=None):
|
|
650
|
+
if virtual_id is None and physical_id is None:
|
|
651
|
+
from nervapy.common.function import active_function
|
|
652
|
+
|
|
653
|
+
super(MMXRegister, self).__init__(
|
|
654
|
+
MMXRegister._mask, active_function._allocate_mmx_register_id()
|
|
655
|
+
)
|
|
656
|
+
else:
|
|
657
|
+
super(MMXRegister, self).__init__(
|
|
658
|
+
MMXRegister._mask, virtual_id, physical_id
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
def __str__(self):
|
|
662
|
+
if self.is_virtual:
|
|
663
|
+
return "mm-vreg<%d>" % self.virtual_id
|
|
664
|
+
else:
|
|
665
|
+
return MMXRegister._physical_id_map[self.physical_id]
|
|
666
|
+
|
|
667
|
+
def format(self, assembly_format):
|
|
668
|
+
assert assembly_format in {
|
|
669
|
+
"peachpy",
|
|
670
|
+
"gas",
|
|
671
|
+
"nasm",
|
|
672
|
+
"go",
|
|
673
|
+
}, "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
|
|
674
|
+
|
|
675
|
+
if assembly_format == "go":
|
|
676
|
+
assert (
|
|
677
|
+
not self.is_virtual
|
|
678
|
+
), "Go assembler does not support virtual registers"
|
|
679
|
+
return MMXRegister._go_physical_id_map[self.physical_id]
|
|
680
|
+
elif assembly_format == "gas":
|
|
681
|
+
return "%" + str(self)
|
|
682
|
+
else:
|
|
683
|
+
return str(self)
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
mm0 = MMXRegister(0)
|
|
687
|
+
mm1 = MMXRegister(1)
|
|
688
|
+
mm2 = MMXRegister(2)
|
|
689
|
+
mm3 = MMXRegister(3)
|
|
690
|
+
mm4 = MMXRegister(4)
|
|
691
|
+
mm5 = MMXRegister(5)
|
|
692
|
+
mm6 = MMXRegister(6)
|
|
693
|
+
mm7 = MMXRegister(7)
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
class XMMRegister(Register):
|
|
697
|
+
"""128-bit xmm (SSE) register"""
|
|
698
|
+
|
|
699
|
+
size = 16
|
|
700
|
+
|
|
701
|
+
_physical_id_map = {n: "xmm" + str(n) for n in range(32)}
|
|
702
|
+
_go_physical_id_map = {n: "X" + str(n) for n in range(16)}
|
|
703
|
+
_kind = 3
|
|
704
|
+
_mask = 0x100
|
|
705
|
+
|
|
706
|
+
def __init__(self, physical_id=None, virtual_id=None):
|
|
707
|
+
if virtual_id is None and physical_id is None:
|
|
708
|
+
from nervapy.common.function import active_function
|
|
709
|
+
|
|
710
|
+
super(XMMRegister, self).__init__(
|
|
711
|
+
XMMRegister._mask, active_function._allocate_xmm_register_id()
|
|
712
|
+
)
|
|
713
|
+
else:
|
|
714
|
+
super(XMMRegister, self).__init__(
|
|
715
|
+
XMMRegister._mask, virtual_id, physical_id
|
|
716
|
+
)
|
|
717
|
+
|
|
718
|
+
def __str__(self):
|
|
719
|
+
if self.is_virtual:
|
|
720
|
+
return "xmm-vreg<%d>" % self.virtual_id
|
|
721
|
+
else:
|
|
722
|
+
return XMMRegister._physical_id_map[self.physical_id]
|
|
723
|
+
|
|
724
|
+
def format(self, assembly_format):
|
|
725
|
+
assert assembly_format in {
|
|
726
|
+
"peachpy",
|
|
727
|
+
"gas",
|
|
728
|
+
"nasm",
|
|
729
|
+
"go",
|
|
730
|
+
}, "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
|
|
731
|
+
|
|
732
|
+
if assembly_format == "go":
|
|
733
|
+
assert (
|
|
734
|
+
not self.is_virtual
|
|
735
|
+
), "Go assembler does not support virtual registers"
|
|
736
|
+
return XMMRegister._go_physical_id_map[self.physical_id]
|
|
737
|
+
elif assembly_format == "gas":
|
|
738
|
+
return "%" + str(self)
|
|
739
|
+
else:
|
|
740
|
+
return str(self)
|
|
741
|
+
|
|
742
|
+
@property
|
|
743
|
+
def as_xmm(self):
|
|
744
|
+
return XMMRegister(self.physical_id, self.virtual_id)
|
|
745
|
+
|
|
746
|
+
@property
|
|
747
|
+
def as_ymm(self):
|
|
748
|
+
return YMMRegister(self.physical_id, self.virtual_id)
|
|
749
|
+
|
|
750
|
+
@property
|
|
751
|
+
def as_zmm(self):
|
|
752
|
+
return ZMMRegister(self.physical_id, self.virtual_id)
|
|
753
|
+
|
|
754
|
+
@property
|
|
755
|
+
def code(self):
|
|
756
|
+
"""Returns 5-bit encoding of the register"""
|
|
757
|
+
assert (
|
|
758
|
+
self.physical_id is not None
|
|
759
|
+
), "The method returns encoding detail for a physical register"
|
|
760
|
+
return self.physical_id
|
|
761
|
+
|
|
762
|
+
@property
|
|
763
|
+
def kcode(self):
|
|
764
|
+
"""Returns encoding of mask register"""
|
|
765
|
+
return 0
|
|
766
|
+
|
|
767
|
+
@property
|
|
768
|
+
def zcode(self):
|
|
769
|
+
"""Returns encoding of zeroing/merging flag of mask register"""
|
|
770
|
+
return 0
|
|
771
|
+
|
|
772
|
+
def __call__(self, mask):
|
|
773
|
+
if not isinstance(mask, (KRegister, RegisterMask)):
|
|
774
|
+
raise SyntaxError(
|
|
775
|
+
"xmm(mask) syntax requires mask to be a KRegister or KRegister.z"
|
|
776
|
+
)
|
|
777
|
+
return MaskedRegister(self, mask)
|
|
778
|
+
|
|
779
|
+
def __mul__(self, scale):
|
|
780
|
+
from nervapy.util import is_int
|
|
781
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
782
|
+
|
|
783
|
+
if not is_int(scale):
|
|
784
|
+
raise TypeError("Register can be scaled only by an integer number")
|
|
785
|
+
if int(scale) not in {1, 2, 4, 8}:
|
|
786
|
+
raise ValueError(
|
|
787
|
+
"Invalid scale value (%d): only scaling by 1, 2, 4, or 8 is supported"
|
|
788
|
+
% scale
|
|
789
|
+
)
|
|
790
|
+
return MemoryAddress(index=self, scale=scale)
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
xmm0 = XMMRegister(0)
|
|
794
|
+
xmm1 = XMMRegister(1)
|
|
795
|
+
xmm2 = XMMRegister(2)
|
|
796
|
+
xmm3 = XMMRegister(3)
|
|
797
|
+
xmm4 = XMMRegister(4)
|
|
798
|
+
xmm5 = XMMRegister(5)
|
|
799
|
+
xmm6 = XMMRegister(6)
|
|
800
|
+
xmm7 = XMMRegister(7)
|
|
801
|
+
xmm8 = XMMRegister(8)
|
|
802
|
+
xmm9 = XMMRegister(9)
|
|
803
|
+
xmm10 = XMMRegister(10)
|
|
804
|
+
xmm11 = XMMRegister(11)
|
|
805
|
+
xmm12 = XMMRegister(12)
|
|
806
|
+
xmm13 = XMMRegister(13)
|
|
807
|
+
xmm14 = XMMRegister(14)
|
|
808
|
+
xmm15 = XMMRegister(15)
|
|
809
|
+
xmm16 = XMMRegister(16)
|
|
810
|
+
xmm17 = XMMRegister(17)
|
|
811
|
+
xmm18 = XMMRegister(18)
|
|
812
|
+
xmm19 = XMMRegister(19)
|
|
813
|
+
xmm20 = XMMRegister(20)
|
|
814
|
+
xmm21 = XMMRegister(21)
|
|
815
|
+
xmm22 = XMMRegister(22)
|
|
816
|
+
xmm23 = XMMRegister(23)
|
|
817
|
+
xmm24 = XMMRegister(24)
|
|
818
|
+
xmm25 = XMMRegister(25)
|
|
819
|
+
xmm26 = XMMRegister(26)
|
|
820
|
+
xmm27 = XMMRegister(27)
|
|
821
|
+
xmm28 = XMMRegister(28)
|
|
822
|
+
xmm29 = XMMRegister(29)
|
|
823
|
+
xmm30 = XMMRegister(30)
|
|
824
|
+
xmm31 = XMMRegister(31)
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
class YMMRegister(Register):
|
|
828
|
+
"""256-bit ymm (AVX) register"""
|
|
829
|
+
|
|
830
|
+
size = 32
|
|
831
|
+
|
|
832
|
+
_physical_id_map = {n: "ymm" + str(n) for n in range(32)}
|
|
833
|
+
_kind = 3
|
|
834
|
+
_mask = 0x300
|
|
835
|
+
|
|
836
|
+
def __init__(self, physical_id=None, virtual_id=None):
|
|
837
|
+
if virtual_id is None and physical_id is None:
|
|
838
|
+
from nervapy.common.function import active_function
|
|
839
|
+
|
|
840
|
+
super(YMMRegister, self).__init__(
|
|
841
|
+
YMMRegister._mask, active_function._allocate_xmm_register_id()
|
|
842
|
+
)
|
|
843
|
+
else:
|
|
844
|
+
super(YMMRegister, self).__init__(
|
|
845
|
+
YMMRegister._mask, virtual_id, physical_id
|
|
846
|
+
)
|
|
847
|
+
|
|
848
|
+
def __str__(self):
|
|
849
|
+
if self.is_virtual:
|
|
850
|
+
return "ymm-vreg<%d>" % self.virtual_id
|
|
851
|
+
else:
|
|
852
|
+
return YMMRegister._physical_id_map[self.physical_id]
|
|
853
|
+
|
|
854
|
+
def format(self, assembly_format):
|
|
855
|
+
assert assembly_format in {
|
|
856
|
+
"peachpy",
|
|
857
|
+
"gas",
|
|
858
|
+
"nasm",
|
|
859
|
+
"go",
|
|
860
|
+
}, "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
|
|
861
|
+
|
|
862
|
+
if assembly_format == "go":
|
|
863
|
+
assert (
|
|
864
|
+
not self.is_virtual
|
|
865
|
+
), "Go assembler does not support virtual registers"
|
|
866
|
+
return XMMRegister._go_physical_id_map[self.physical_id]
|
|
867
|
+
elif assembly_format == "gas":
|
|
868
|
+
return "%" + str(self)
|
|
869
|
+
else:
|
|
870
|
+
return str(self)
|
|
871
|
+
|
|
872
|
+
@property
|
|
873
|
+
def as_xmm(self):
|
|
874
|
+
return XMMRegister(self.physical_id, self.virtual_id)
|
|
875
|
+
|
|
876
|
+
@property
|
|
877
|
+
def as_ymm(self):
|
|
878
|
+
return YMMRegister(self.physical_id, self.virtual_id)
|
|
879
|
+
|
|
880
|
+
@property
|
|
881
|
+
def as_zmm(self):
|
|
882
|
+
return ZMMRegister(self.physical_id, self.virtual_id)
|
|
883
|
+
|
|
884
|
+
@property
|
|
885
|
+
def code(self):
|
|
886
|
+
"""Returns 5-bit encoding of the register"""
|
|
887
|
+
assert (
|
|
888
|
+
self.physical_id is not None
|
|
889
|
+
), "The method returns encoding detail for a physical register"
|
|
890
|
+
return self.physical_id
|
|
891
|
+
|
|
892
|
+
@property
|
|
893
|
+
def kcode(self):
|
|
894
|
+
"""Returns encoding of mask register"""
|
|
895
|
+
return 0
|
|
896
|
+
|
|
897
|
+
@property
|
|
898
|
+
def zcode(self):
|
|
899
|
+
"""Returns encoding of zeroing/merging flag of mask register"""
|
|
900
|
+
return 0
|
|
901
|
+
|
|
902
|
+
def __call__(self, mask):
|
|
903
|
+
if not isinstance(mask, (KRegister, RegisterMask)):
|
|
904
|
+
raise SyntaxError(
|
|
905
|
+
"ymm(mask) syntax requires mask to be a KRegister or KRegister.z"
|
|
906
|
+
)
|
|
907
|
+
return MaskedRegister(self, mask)
|
|
908
|
+
|
|
909
|
+
def __mul__(self, scale):
|
|
910
|
+
from nervapy.util import is_int
|
|
911
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
912
|
+
|
|
913
|
+
if not is_int(scale):
|
|
914
|
+
raise TypeError("Register can be scaled only by an integer number")
|
|
915
|
+
if int(scale) not in {1, 2, 4, 8}:
|
|
916
|
+
raise ValueError(
|
|
917
|
+
"Invalid scale value (%d): only scaling by 1, 2, 4, or 8 is supported"
|
|
918
|
+
% scale
|
|
919
|
+
)
|
|
920
|
+
return MemoryAddress(index=self, scale=scale)
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
ymm0 = YMMRegister(0)
|
|
924
|
+
ymm1 = YMMRegister(1)
|
|
925
|
+
ymm2 = YMMRegister(2)
|
|
926
|
+
ymm3 = YMMRegister(3)
|
|
927
|
+
ymm4 = YMMRegister(4)
|
|
928
|
+
ymm5 = YMMRegister(5)
|
|
929
|
+
ymm6 = YMMRegister(6)
|
|
930
|
+
ymm7 = YMMRegister(7)
|
|
931
|
+
ymm8 = YMMRegister(8)
|
|
932
|
+
ymm9 = YMMRegister(9)
|
|
933
|
+
ymm10 = YMMRegister(10)
|
|
934
|
+
ymm11 = YMMRegister(11)
|
|
935
|
+
ymm12 = YMMRegister(12)
|
|
936
|
+
ymm13 = YMMRegister(13)
|
|
937
|
+
ymm14 = YMMRegister(14)
|
|
938
|
+
ymm15 = YMMRegister(15)
|
|
939
|
+
ymm16 = YMMRegister(16)
|
|
940
|
+
ymm17 = YMMRegister(17)
|
|
941
|
+
ymm18 = YMMRegister(18)
|
|
942
|
+
ymm19 = YMMRegister(19)
|
|
943
|
+
ymm20 = YMMRegister(20)
|
|
944
|
+
ymm21 = YMMRegister(21)
|
|
945
|
+
ymm22 = YMMRegister(22)
|
|
946
|
+
ymm23 = YMMRegister(23)
|
|
947
|
+
ymm24 = YMMRegister(24)
|
|
948
|
+
ymm25 = YMMRegister(25)
|
|
949
|
+
ymm26 = YMMRegister(26)
|
|
950
|
+
ymm27 = YMMRegister(27)
|
|
951
|
+
ymm28 = YMMRegister(28)
|
|
952
|
+
ymm29 = YMMRegister(29)
|
|
953
|
+
ymm30 = YMMRegister(30)
|
|
954
|
+
ymm31 = YMMRegister(31)
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
class ZMMRegister(Register):
|
|
958
|
+
"""512-bit zmm (AVX-512) register"""
|
|
959
|
+
|
|
960
|
+
size = 64
|
|
961
|
+
|
|
962
|
+
_physical_id_map = {n: "zmm" + str(n) for n in range(32)}
|
|
963
|
+
_kind = 3
|
|
964
|
+
_mask = 0x700
|
|
965
|
+
|
|
966
|
+
def __init__(self, physical_id=None, virtual_id=None):
|
|
967
|
+
if virtual_id is None and physical_id is None:
|
|
968
|
+
from nervapy.common.function import active_function
|
|
969
|
+
|
|
970
|
+
super(ZMMRegister, self).__init__(
|
|
971
|
+
ZMMRegister._mask, active_function._allocate_xmm_register_id()
|
|
972
|
+
)
|
|
973
|
+
else:
|
|
974
|
+
super(ZMMRegister, self).__init__(
|
|
975
|
+
ZMMRegister._mask, virtual_id, physical_id
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
def __str__(self):
|
|
979
|
+
if self.is_virtual:
|
|
980
|
+
return "zmm-vreg<%d>" % self.virtual_id
|
|
981
|
+
else:
|
|
982
|
+
return ZMMRegister._physical_id_map[self.physical_id]
|
|
983
|
+
|
|
984
|
+
@property
|
|
985
|
+
def as_xmm(self):
|
|
986
|
+
return XMMRegister(self.physical_id, self.virtual_id)
|
|
987
|
+
|
|
988
|
+
@property
|
|
989
|
+
def as_ymm(self):
|
|
990
|
+
return YMMRegister(self.physical_id, self.virtual_id)
|
|
991
|
+
|
|
992
|
+
@property
|
|
993
|
+
def as_zmm(self):
|
|
994
|
+
return ZMMRegister(self.physical_id, self.virtual_id)
|
|
995
|
+
|
|
996
|
+
@property
|
|
997
|
+
def code(self):
|
|
998
|
+
"""Returns 5-bit encoding of the register"""
|
|
999
|
+
assert (
|
|
1000
|
+
self.physical_id is not None
|
|
1001
|
+
), "The method returns encoding detail for a physical register"
|
|
1002
|
+
return self.physical_id
|
|
1003
|
+
|
|
1004
|
+
@property
|
|
1005
|
+
def kcode(self):
|
|
1006
|
+
"""Returns encoding of mask register"""
|
|
1007
|
+
return 0
|
|
1008
|
+
|
|
1009
|
+
@property
|
|
1010
|
+
def zcode(self):
|
|
1011
|
+
"""Returns encoding of zeroing/merging flag of mask register"""
|
|
1012
|
+
return 0
|
|
1013
|
+
|
|
1014
|
+
def __call__(self, mask):
|
|
1015
|
+
if not isinstance(mask, (KRegister, RegisterMask)):
|
|
1016
|
+
raise SyntaxError(
|
|
1017
|
+
"zmm(mask) syntax requires mask to be a KRegister or KRegister.z"
|
|
1018
|
+
)
|
|
1019
|
+
return MaskedRegister(self, mask)
|
|
1020
|
+
|
|
1021
|
+
def __mul__(self, scale):
|
|
1022
|
+
from nervapy.util import is_int
|
|
1023
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
1024
|
+
|
|
1025
|
+
if not is_int(scale):
|
|
1026
|
+
raise TypeError("Register can be scaled only by an integer number")
|
|
1027
|
+
if int(scale) not in {1, 2, 4, 8}:
|
|
1028
|
+
raise ValueError(
|
|
1029
|
+
"Invalid scale value (%d): only scaling by 1, 2, 4, or 8 is supported"
|
|
1030
|
+
% scale
|
|
1031
|
+
)
|
|
1032
|
+
return MemoryAddress(index=self, scale=scale)
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
zmm0 = ZMMRegister(0)
|
|
1036
|
+
zmm1 = ZMMRegister(1)
|
|
1037
|
+
zmm2 = ZMMRegister(2)
|
|
1038
|
+
zmm3 = ZMMRegister(3)
|
|
1039
|
+
zmm4 = ZMMRegister(4)
|
|
1040
|
+
zmm5 = ZMMRegister(5)
|
|
1041
|
+
zmm6 = ZMMRegister(6)
|
|
1042
|
+
zmm7 = ZMMRegister(7)
|
|
1043
|
+
zmm8 = ZMMRegister(8)
|
|
1044
|
+
zmm9 = ZMMRegister(9)
|
|
1045
|
+
zmm10 = ZMMRegister(10)
|
|
1046
|
+
zmm11 = ZMMRegister(11)
|
|
1047
|
+
zmm12 = ZMMRegister(12)
|
|
1048
|
+
zmm13 = ZMMRegister(13)
|
|
1049
|
+
zmm14 = ZMMRegister(14)
|
|
1050
|
+
zmm15 = ZMMRegister(15)
|
|
1051
|
+
zmm16 = ZMMRegister(16)
|
|
1052
|
+
zmm17 = ZMMRegister(17)
|
|
1053
|
+
zmm18 = ZMMRegister(18)
|
|
1054
|
+
zmm19 = ZMMRegister(19)
|
|
1055
|
+
zmm20 = ZMMRegister(20)
|
|
1056
|
+
zmm21 = ZMMRegister(21)
|
|
1057
|
+
zmm22 = ZMMRegister(22)
|
|
1058
|
+
zmm23 = ZMMRegister(23)
|
|
1059
|
+
zmm24 = ZMMRegister(24)
|
|
1060
|
+
zmm25 = ZMMRegister(25)
|
|
1061
|
+
zmm26 = ZMMRegister(26)
|
|
1062
|
+
zmm27 = ZMMRegister(27)
|
|
1063
|
+
zmm28 = ZMMRegister(28)
|
|
1064
|
+
zmm29 = ZMMRegister(29)
|
|
1065
|
+
zmm30 = ZMMRegister(30)
|
|
1066
|
+
zmm31 = ZMMRegister(31)
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
class KRegister(Register):
|
|
1070
|
+
"""AVX-512 mask register"""
|
|
1071
|
+
|
|
1072
|
+
size = 8
|
|
1073
|
+
|
|
1074
|
+
_physical_id_map = {n: "k" + str(n) for n in range(8)}
|
|
1075
|
+
_kind = 4
|
|
1076
|
+
_mask = 0x40
|
|
1077
|
+
|
|
1078
|
+
def __init__(self, physical_id=None, virtual_id=None):
|
|
1079
|
+
if virtual_id is None and physical_id is None:
|
|
1080
|
+
from nervapy.common.function import active_function
|
|
1081
|
+
|
|
1082
|
+
super(KRegister, self).__init__(
|
|
1083
|
+
KRegister._mask, active_function._allocate_mask_register_id()
|
|
1084
|
+
)
|
|
1085
|
+
else:
|
|
1086
|
+
super(KRegister, self).__init__(KRegister._mask, virtual_id, physical_id)
|
|
1087
|
+
|
|
1088
|
+
def __str__(self):
|
|
1089
|
+
if self.is_virtual:
|
|
1090
|
+
return "k-vreg<%d>" % self.virtual_id
|
|
1091
|
+
else:
|
|
1092
|
+
return KRegister._physical_id_map[self.physical_id]
|
|
1093
|
+
|
|
1094
|
+
@property
|
|
1095
|
+
def z(self):
|
|
1096
|
+
return RegisterMask(self, is_zeroing=True)
|
|
1097
|
+
|
|
1098
|
+
@property
|
|
1099
|
+
def kcode(self):
|
|
1100
|
+
"""Returns the register encoding"""
|
|
1101
|
+
assert (
|
|
1102
|
+
self.physical_id is not None
|
|
1103
|
+
), "The method returns encoding detail for a physical register"
|
|
1104
|
+
return self.physical_id
|
|
1105
|
+
|
|
1106
|
+
@property
|
|
1107
|
+
def zcode(self):
|
|
1108
|
+
"""Returns encoding of the merge/zero flags"""
|
|
1109
|
+
return 0
|
|
1110
|
+
|
|
1111
|
+
def __call__(self, mask):
|
|
1112
|
+
if not isinstance(mask, KRegister):
|
|
1113
|
+
raise SyntaxError("k(mask) syntax requires mask to be a KRegister")
|
|
1114
|
+
return MaskedRegister(self, mask)
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
class RegisterMask:
|
|
1118
|
+
def __init__(self, mask_register, is_zeroing=False):
|
|
1119
|
+
self.mask_register = mask_register
|
|
1120
|
+
self.is_zeroing = is_zeroing
|
|
1121
|
+
|
|
1122
|
+
@property
|
|
1123
|
+
def kcode(self):
|
|
1124
|
+
"""Returns encoding of the mask register"""
|
|
1125
|
+
return self.mask_register.kcode
|
|
1126
|
+
|
|
1127
|
+
@property
|
|
1128
|
+
def zcode(self):
|
|
1129
|
+
"""Returns encoding of the merge/zero flags"""
|
|
1130
|
+
return int(self.is_zeroing)
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
k0 = KRegister(0)
|
|
1134
|
+
k1 = KRegister(1)
|
|
1135
|
+
k2 = KRegister(2)
|
|
1136
|
+
k3 = KRegister(3)
|
|
1137
|
+
k4 = KRegister(4)
|
|
1138
|
+
k5 = KRegister(5)
|
|
1139
|
+
k6 = KRegister(6)
|
|
1140
|
+
k7 = KRegister(7)
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
class MaskedRegister:
|
|
1144
|
+
def __init__(self, register, mask):
|
|
1145
|
+
assert isinstance(register, (XMMRegister, YMMRegister, ZMMRegister, KRegister))
|
|
1146
|
+
assert isinstance(mask, (KRegister, RegisterMask))
|
|
1147
|
+
self.register = register
|
|
1148
|
+
if isinstance(mask, KRegister):
|
|
1149
|
+
self.mask = RegisterMask(mask)
|
|
1150
|
+
else:
|
|
1151
|
+
self.mask = mask
|
|
1152
|
+
|
|
1153
|
+
@property
|
|
1154
|
+
def code(self):
|
|
1155
|
+
"""Returns the 5-bit register encoding"""
|
|
1156
|
+
return self.register.code
|
|
1157
|
+
|
|
1158
|
+
@property
|
|
1159
|
+
def lcode(self):
|
|
1160
|
+
"""Returns the bits 0-2 of register encoding"""
|
|
1161
|
+
return self.register.lcode
|
|
1162
|
+
|
|
1163
|
+
@property
|
|
1164
|
+
def hcode(self):
|
|
1165
|
+
"""Returns the bit 3 of register encoding"""
|
|
1166
|
+
return self.register.hcode
|
|
1167
|
+
|
|
1168
|
+
@property
|
|
1169
|
+
def ecode(self):
|
|
1170
|
+
"""Returns the bit 4 of register encoding"""
|
|
1171
|
+
return self.register.ecode
|
|
1172
|
+
|
|
1173
|
+
@property
|
|
1174
|
+
def hlcode(self):
|
|
1175
|
+
"""Returns the bits 0-3 of register encoding"""
|
|
1176
|
+
return self.register.hlcode
|
|
1177
|
+
|
|
1178
|
+
@property
|
|
1179
|
+
def ehcode(self):
|
|
1180
|
+
"""Returns the bits 3-4 of register encoding"""
|
|
1181
|
+
return self.register.ehcode
|
|
1182
|
+
|
|
1183
|
+
@property
|
|
1184
|
+
def kcode(self):
|
|
1185
|
+
"""Returns encoding of mask register"""
|
|
1186
|
+
return self.mask.kcode
|
|
1187
|
+
|
|
1188
|
+
@property
|
|
1189
|
+
def zcode(self):
|
|
1190
|
+
"""Returns encoding of zeroing/merging flag of mask register"""
|
|
1191
|
+
return self.mask.zcode
|
|
1192
|
+
|
|
1193
|
+
def __mul__(self, scale):
|
|
1194
|
+
from nervapy.util import is_int
|
|
1195
|
+
from nervapy.x86_64.operand import MemoryAddress
|
|
1196
|
+
|
|
1197
|
+
if not is_int(scale):
|
|
1198
|
+
raise TypeError("Register can be scaled only by an integer number")
|
|
1199
|
+
if int(scale) not in {1, 2, 4, 8}:
|
|
1200
|
+
raise ValueError(
|
|
1201
|
+
"Invalid scale value (%d): only scaling by 1, 2, 4, or 8 is supported"
|
|
1202
|
+
% scale
|
|
1203
|
+
)
|
|
1204
|
+
return MemoryAddress(index=self, scale=scale)
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
class RIPRegister:
|
|
1208
|
+
def __init__(self):
|
|
1209
|
+
pass
|
|
1210
|
+
|
|
1211
|
+
def __str__(self):
|
|
1212
|
+
return "rip"
|
|
1213
|
+
|
|
1214
|
+
def __add__(self, offset):
|
|
1215
|
+
from nervapy.x86_64.operand import RIPRelativeOffset
|
|
1216
|
+
|
|
1217
|
+
return RIPRelativeOffset(offset)
|
|
1218
|
+
|
|
1219
|
+
def __sub__(self, offset):
|
|
1220
|
+
from nervapy.x86_64.operand import RIPRelativeOffset
|
|
1221
|
+
|
|
1222
|
+
return RIPRelativeOffset(-offset)
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
rip = RIPRegister()
|