PyNerva 0.0.7__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.
Files changed (74) hide show
  1. nervapy/__init__.py +50 -0
  2. nervapy/abi.py +91 -0
  3. nervapy/arm/__init__.py +124 -0
  4. nervapy/arm/__main__.py +0 -0
  5. nervapy/arm/abi.py +138 -0
  6. nervapy/arm/formats.py +49 -0
  7. nervapy/arm/function.py +2465 -0
  8. nervapy/arm/generic.py +10796 -0
  9. nervapy/arm/instructions.py +519 -0
  10. nervapy/arm/isa.py +409 -0
  11. nervapy/arm/literal_pool.py +331 -0
  12. nervapy/arm/microarchitecture.py +211 -0
  13. nervapy/arm/pseudo.py +652 -0
  14. nervapy/arm/registers.py +1458 -0
  15. nervapy/arm/vfpneon.py +4092 -0
  16. nervapy/arm.py +13 -0
  17. nervapy/c/__init__.py +1 -0
  18. nervapy/c/types.py +436 -0
  19. nervapy/codegen.py +99 -0
  20. nervapy/common/__init__.py +4 -0
  21. nervapy/common/function.py +5 -0
  22. nervapy/common/regalloc.py +121 -0
  23. nervapy/constant_data.py +282 -0
  24. nervapy/encoder.py +246 -0
  25. nervapy/formats/__init__.py +2 -0
  26. nervapy/formats/elf/__init__.py +4 -0
  27. nervapy/formats/elf/file.py +178 -0
  28. nervapy/formats/elf/image.py +106 -0
  29. nervapy/formats/elf/section.py +422 -0
  30. nervapy/formats/elf/symbol.py +281 -0
  31. nervapy/formats/macho/__init__.py +2 -0
  32. nervapy/formats/macho/file.py +123 -0
  33. nervapy/formats/macho/image.py +143 -0
  34. nervapy/formats/macho/section.py +322 -0
  35. nervapy/formats/macho/symbol.py +158 -0
  36. nervapy/formats/mscoff/__init__.py +8 -0
  37. nervapy/formats/mscoff/image.py +132 -0
  38. nervapy/formats/mscoff/section.py +181 -0
  39. nervapy/formats/mscoff/symbol.py +148 -0
  40. nervapy/function.py +136 -0
  41. nervapy/literal.py +731 -0
  42. nervapy/loader.py +188 -0
  43. nervapy/name.py +159 -0
  44. nervapy/parse.py +52 -0
  45. nervapy/stream.py +58 -0
  46. nervapy/util.py +126 -0
  47. nervapy/writer.py +518 -0
  48. nervapy/x86_64/__init__.py +324 -0
  49. nervapy/x86_64/__main__.py +407 -0
  50. nervapy/x86_64/abi.py +517 -0
  51. nervapy/x86_64/amd.py +6464 -0
  52. nervapy/x86_64/avx.py +102029 -0
  53. nervapy/x86_64/crypto.py +1533 -0
  54. nervapy/x86_64/encoding.py +424 -0
  55. nervapy/x86_64/fma.py +19138 -0
  56. nervapy/x86_64/function.py +2707 -0
  57. nervapy/x86_64/generic.py +23384 -0
  58. nervapy/x86_64/instructions.py +500 -0
  59. nervapy/x86_64/isa.py +476 -0
  60. nervapy/x86_64/lower.py +126 -0
  61. nervapy/x86_64/mask.py +2593 -0
  62. nervapy/x86_64/meta.py +143 -0
  63. nervapy/x86_64/mmxsse.py +17265 -0
  64. nervapy/x86_64/nacl.py +327 -0
  65. nervapy/x86_64/operand.py +1204 -0
  66. nervapy/x86_64/options.py +21 -0
  67. nervapy/x86_64/pseudo.py +686 -0
  68. nervapy/x86_64/registers.py +1225 -0
  69. nervapy/x86_64/types.py +17 -0
  70. nervapy/x86_64/uarch.py +580 -0
  71. pynerva-0.0.7.dist-info/METADATA +310 -0
  72. pynerva-0.0.7.dist-info/RECORD +74 -0
  73. pynerva-0.0.7.dist-info/WHEEL +4 -0
  74. pynerva-0.0.7.dist-info/licenses/LICENSE.rst +15 -0
@@ -0,0 +1,686 @@
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
+ import inspect
5
+
6
+ import nervapy.stream
7
+ import nervapy.x86_64.isa
8
+ import nervapy.x86_64.options
9
+ from nervapy.parse import (parse_assigned_variable_name,
10
+ parse_with_variable_name)
11
+ from nervapy.x86_64.instructions import Instruction
12
+ from nervapy.x86_64.operand import check_operand, format_operand_type
13
+
14
+
15
+ class Label:
16
+ def __init__(self, name=None):
17
+ from nervapy.name import Name
18
+
19
+ if name is None:
20
+ import inspect
21
+
22
+ self.name = (
23
+ Name(prename=parse_assigned_variable_name(inspect.stack(), "Label")),
24
+ )
25
+ elif isinstance(name, tuple):
26
+ assert all(
27
+ isinstance(part, Name) for part in name
28
+ ), "Name must a string or a tuple or Name objects"
29
+ self.name = name
30
+ else:
31
+ Name.check_name(name)
32
+ self.name = (Name(name=name),)
33
+ self.line_number = None
34
+
35
+ def __str__(self):
36
+ """Returns a string representation of the name"""
37
+ return ".".join(map(str, self.name))
38
+
39
+ def format(self, assembly_format):
40
+ assert assembly_format in {
41
+ "peachpy",
42
+ "gas",
43
+ "nasm",
44
+ "go",
45
+ }, "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
46
+
47
+ if assembly_format == "go":
48
+ # Go assembler rejects label names with a dot, so we replace it with underscore symbol
49
+ return str(self).replace(".", "_")
50
+ else:
51
+ return str(self)
52
+
53
+ @property
54
+ def is_named(self):
55
+ return not any(part.name is None for part in self.name)
56
+
57
+
58
+ class LABEL(Instruction):
59
+ def __init__(self, label, origin=None):
60
+ label = check_operand(label)
61
+ super(LABEL, self).__init__("LABEL", origin=origin)
62
+ self.operands = (label,)
63
+ if not isinstance(label, Label):
64
+ raise SyntaxError(
65
+ "Invalid operand for LABEL statement: Label object expected"
66
+ )
67
+ self.identifier = label.name
68
+ self.input_branches = set()
69
+ if nervapy.stream.active_stream is not None:
70
+ nervapy.stream.active_stream.add_instruction(self)
71
+
72
+ def __str__(self):
73
+ return ".".join(map(str, self.identifier)) + ":"
74
+
75
+ def format(self, assembly_format, indent=False, line_number=None):
76
+ assert assembly_format in {
77
+ "peachpy",
78
+ "gas",
79
+ "nasm",
80
+ "go",
81
+ }, "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
82
+
83
+ if assembly_format == "go":
84
+ # Go assembler rejects label names with a dot, so we replace it with underscore symbol
85
+ return "_".join(map(str, self.identifier)) + ":"
86
+ elif assembly_format == "gas":
87
+ # GAS doesn't support named non-local labels
88
+ if self.operands[0].line_number is None:
89
+ return "." + str(self) + ":"
90
+ else:
91
+ return str(self.operands[0].line_number) + ": # " + str(self)
92
+ else:
93
+ return str(self)
94
+
95
+ def __enter__(self):
96
+ return self
97
+
98
+ def __exit__(self, exc_type, exc_value, traceback):
99
+ if exc_type is not None:
100
+ raise
101
+
102
+
103
+ class Loop:
104
+ def __init__(self, name=None):
105
+ from nervapy.name import Name
106
+
107
+ if name is None:
108
+ import inspect
109
+
110
+ prename = parse_assigned_variable_name(inspect.stack(), "Loop")
111
+ if prename is None:
112
+ prename = parse_with_variable_name(inspect.stack(), "Loop")
113
+ self.name = (Name(prename=prename),)
114
+ elif isinstance(name, tuple):
115
+ assert all(
116
+ isinstance(part, Name) for part in name
117
+ ), "Name must a string or a tuple or Name objects"
118
+ self.name = name
119
+ else:
120
+ Name.check_name(name)
121
+ self.name = (Name(name=name),)
122
+ self.begin = Label(self.name + (Name(name="begin"),))
123
+ self.end = Label(self.name + (Name(name="end"),))
124
+
125
+ def __enter__(self):
126
+ LABEL(self.begin)
127
+
128
+ from nervapy.common.function import active_function
129
+
130
+ if active_function is not None:
131
+ active_function._indent_level += 1
132
+ return self
133
+
134
+ def __exit__(self, exc_type, exc_value, exc_traceback):
135
+ from nervapy.common.function import active_function
136
+
137
+ if active_function is not None:
138
+ active_function._indent_level -= 1
139
+
140
+ if exc_type is None:
141
+ LABEL(self.end)
142
+ else:
143
+ raise
144
+
145
+
146
+ class Block:
147
+ def __init__(self, name=None):
148
+ from nervapy.name import Name
149
+
150
+ if name is None:
151
+ import inspect
152
+
153
+ prename = parse_assigned_variable_name(inspect.stack(), "Block")
154
+ if prename is None:
155
+ prename = parse_with_variable_name(inspect.stack(), "Block")
156
+ self.name = (Name(prename=prename),)
157
+ elif isinstance(name, tuple):
158
+ assert all(
159
+ isinstance(part, Name) for part in name
160
+ ), "Name must a string or a tuple or Name objects"
161
+ self.name = name
162
+ else:
163
+ Name.check_name(name)
164
+ self.name = (Name(name=name),)
165
+ self.begin = Label(self.name + (Name(name="begin"),))
166
+ self.end = Label(self.name + (Name(name="end"),))
167
+
168
+ def __enter__(self):
169
+ LABEL(self.begin)
170
+
171
+ from nervapy.common.function import active_function
172
+
173
+ if active_function is not None:
174
+ active_function._indent_level += 1
175
+ return self
176
+
177
+ def __exit__(self, exc_type, exc_value, exc_traceback):
178
+ from nervapy.common.function import active_function
179
+
180
+ if active_function is not None:
181
+ active_function._indent_level -= 1
182
+
183
+ if exc_type is None:
184
+ LABEL(self.end)
185
+ else:
186
+ raise
187
+
188
+
189
+ class ALIGN(Instruction):
190
+ supported_alignments = (2, 4, 8, 16, 32)
191
+
192
+ def __init__(self, alignment, origin=None):
193
+ super(ALIGN, self).__init__("ALIGN", origin=origin)
194
+ if not isinstance(alignment, int):
195
+ raise TypeError("The alignment value must be an integer")
196
+ if alignment not in ALIGN.supported_alignments:
197
+ raise ValueError(
198
+ "The alignment value {0} is not in the list of supported alignments ({1})".format(
199
+ alignment, ", ".join(ALIGN.supported_alignments)
200
+ )
201
+ )
202
+ self.alignment = alignment
203
+ if nervapy.stream.active_stream is not None:
204
+ nervapy.stream.active_stream.add_instruction(self)
205
+
206
+ def __str__(self):
207
+ return "align {0}".format(self.alignment)
208
+
209
+
210
+ class RETURN(Instruction):
211
+ def __init__(self, *args, **kwargs):
212
+ from nervapy.common.function import active_function
213
+ from nervapy.x86_64.registers import (GeneralPurposeRegister,
214
+ MMXRegister, XMMRegister,
215
+ YMMRegister)
216
+
217
+ origin = kwargs.get("origin")
218
+ prototype = kwargs.get("prototype")
219
+ if (
220
+ origin is None
221
+ and prototype is None
222
+ and nervapy.x86_64.options.get_debug_level() > 0
223
+ ):
224
+ origin = inspect.stack()
225
+ super(RETURN, self).__init__("RETURN", origin=origin)
226
+ self.operands = tuple(map(check_operand, args))
227
+ if len(self.operands) == 0:
228
+ # It is not an error to return nothing from a function with a return type
229
+ self.in_regs = tuple()
230
+ self.out_regs = tuple()
231
+ self.out_operands = tuple()
232
+ elif len(self.operands) == 1:
233
+ # It is an error to return something from a void function
234
+ from nervapy.util import int_size, is_int64
235
+
236
+ if active_function.result_type is None:
237
+ raise ValueError("Void function should not return a value")
238
+ if (
239
+ active_function.result_type.is_integer
240
+ or active_function.result_type.is_pointer
241
+ ):
242
+ if is_int64(self.operands[0]):
243
+ if (
244
+ active_function.result_type.size is None
245
+ and int_size(self.operands[0]) > 4
246
+ or active_function.result_type.size is not None
247
+ and active_function.result_type.size
248
+ < int_size(self.operands[0])
249
+ ):
250
+ raise ValueError(
251
+ "Value {0} can not be represented with return type {1}".format(
252
+ str(self.operands[0]), str(active_function.result_type)
253
+ )
254
+ )
255
+ self.in_regs = (False,)
256
+ self.out_regs = (False,)
257
+ self.out_operands = (False,)
258
+ elif isinstance(self.operands[0], GeneralPurposeRegister):
259
+ if active_function.result_type.size < self.operands[0].size:
260
+ raise ValueError(
261
+ "Register {0} can not be converted to return type {1}".format(
262
+ str(self.operands[0]), str(active_function.result_type)
263
+ )
264
+ )
265
+ self.in_regs = (True,)
266
+ self.out_regs = (False,)
267
+ self.out_operands = (False,)
268
+ else:
269
+ raise TypeError(
270
+ "Invalid operand type: RETURN {0} for {1} function".format(
271
+ str(self.operands[0]), str(active_function.result_type)
272
+ )
273
+ )
274
+ elif active_function.result_type.is_floating_point:
275
+ if isinstance(self.operands[0], XMMRegister):
276
+ self.in_regs = (True,)
277
+ self.out_regs = (False,)
278
+ self.out_operands = (False,)
279
+ else:
280
+ raise TypeError(
281
+ "Invalid operand type: RETURN {0} for {1} function".format(
282
+ str(self.operands[0]), str(active_function.result_type)
283
+ )
284
+ )
285
+ elif active_function.result_type.is_vector:
286
+ if (
287
+ isinstance(
288
+ self.operands[0], (MMXRegister, XMMRegister, YMMRegister)
289
+ )
290
+ and active_function.result_type.size == self.operands[0].size
291
+ ):
292
+ self.in_regs = (True,)
293
+ self.out_regs = (False,)
294
+ self.out_operands = (False,)
295
+ else:
296
+ raise TypeError(
297
+ "Invalid operand type: RETURN {0} for {1} function".format(
298
+ str(self.operands[0]), str(active_function.result_type)
299
+ )
300
+ )
301
+ else:
302
+ raise SyntaxError(
303
+ "Invalid operand type: RETURN "
304
+ + ", ".join(map(format_operand_type, self.operands))
305
+ )
306
+ else:
307
+ raise SyntaxError('Pseudo-instruction "RETURN" requires 0 or 1 operands')
308
+ if nervapy.stream.active_stream is not None:
309
+ nervapy.stream.active_stream.add_instruction(self)
310
+
311
+ def __str__(self):
312
+ if len(self.operands) == 0:
313
+ return "RETURN"
314
+ else:
315
+ return "RETURN " + ", ".join(map(str, self.operands))
316
+
317
+ def format(self, assembly_format, indent=False, line_number=None):
318
+ text = "\t" if indent else ""
319
+ if assembly_format == "peachpy":
320
+ return text + str(self)
321
+ else:
322
+ raise SyntaxError('Invalid assembly format "%s"' % assembly_format)
323
+
324
+
325
+ class LOAD:
326
+ class ARGUMENT(Instruction):
327
+ def __init__(self, *args, **kwargs):
328
+ from nervapy.common.function import active_function
329
+ from nervapy.x86_64 import m64
330
+ from nervapy.x86_64.registers import (GeneralPurposeRegister,
331
+ XMMRegister, YMMRegister)
332
+
333
+ origin = kwargs.get("origin")
334
+ prototype = kwargs.get("prototype")
335
+ if (
336
+ origin is None
337
+ and prototype is None
338
+ and nervapy.x86_64.options.get_debug_level() > 0
339
+ ):
340
+ origin = inspect.stack()
341
+ super(LOAD.ARGUMENT, self).__init__("LOAD.ARGUMENT", origin=origin)
342
+ self.operands = tuple(map(check_operand, args))
343
+ self.out_regs = (True, False)
344
+ self.in_regs = (False, False)
345
+ if len(self.operands) != 2:
346
+ raise SyntaxError('Instruction "LOAD.ARGUMENT" requires 2 operands')
347
+
348
+ # Check source (second) operand
349
+ if not isinstance(self.operands[1], nervapy.Argument):
350
+ raise TypeError(
351
+ "The source operand to LOAD.ARGUMENT must be of Argument type"
352
+ )
353
+ argument = active_function._find_argument(self.operands[1])
354
+ if argument is None:
355
+ raise ValueError(
356
+ "%s is not an argument of the active function"
357
+ % str(self.operands[1])
358
+ )
359
+
360
+ # Check destination (first) operand
361
+ if isinstance(self.operands[0], GeneralPurposeRegister) and (
362
+ argument.is_integer or argument.is_pointer
363
+ ):
364
+ if argument.size is not None and self.operands[0].size < argument.size:
365
+ raise ValueError(
366
+ "Destination register %s is too narrow for the argument %s"
367
+ % (self.operands[0], argument)
368
+ )
369
+ elif (
370
+ isinstance(self.operands[0], (XMMRegister, YMMRegister))
371
+ and argument.is_floating_point
372
+ ):
373
+ pass
374
+ elif isinstance(self.operands[0], (XMMRegister, YMMRegister)) and (
375
+ argument.is_vector and argument.c_type != m64
376
+ ):
377
+ pass
378
+ else:
379
+ raise ValueError("Unsupported combination of instruction operands")
380
+
381
+ if nervapy.stream.active_stream is not None:
382
+ nervapy.stream.active_stream.add_instruction(self)
383
+
384
+ def format(self, assembly_format, indent=False, line_number=None):
385
+ assert assembly_format in {
386
+ "peachpy",
387
+ "go",
388
+ }, "Supported assembly formats are 'peachpy' and 'go'"
389
+
390
+ text = "\t" if indent else ""
391
+ if assembly_format == "go":
392
+ from nervapy.x86_64.registers import (GeneralPurposeRegister,
393
+ GeneralPurposeRegister8,
394
+ GeneralPurposeRegister16,
395
+ GeneralPurposeRegister32,
396
+ GeneralPurposeRegister64,
397
+ MMXRegister, XMMRegister,
398
+ YMMRegister)
399
+
400
+ assert isinstance(
401
+ self.operands[0], (GeneralPurposeRegister, MMXRegister, XMMRegister)
402
+ ), "LOAD.ARGUMENT must load into a general-purpose, mmx, or xmm register"
403
+ if isinstance(self.operands[0], GeneralPurposeRegister8):
404
+ return text + "MOVB %s+%d(FP), %s" % (
405
+ self.operands[1].name,
406
+ self.operands[1].stack_offset,
407
+ self.operands[0].format("go"),
408
+ )
409
+ elif isinstance(self.operands[0], GeneralPurposeRegister16):
410
+ mov_name = {
411
+ (True, 1): "MOVWLSX",
412
+ (True, 2): "MOVW",
413
+ (False, 1): "MOVWLZX",
414
+ (False, 2): "MOVW",
415
+ }[(self.operands[1].is_signed_integer, self.operands[1].size)]
416
+ return text + "%s %s+%d(FP), %s" % (
417
+ mov_name,
418
+ self.operands[1].name,
419
+ self.operands[1].stack_offset,
420
+ self.operands[0].format("go"),
421
+ )
422
+ elif isinstance(self.operands[0], GeneralPurposeRegister32):
423
+ mov_name = {
424
+ (True, 1): "MOVBLSX",
425
+ (True, 2): "MOVWLSX",
426
+ (True, 4): "MOVL",
427
+ (False, 1): "MOVBLZX",
428
+ (False, 2): "MOVWLZX",
429
+ (False, 4): "MOVL",
430
+ }[(self.operands[1].is_signed_integer, self.operands[1].size)]
431
+ return text + "%s %s+%d(FP), %s" % (
432
+ mov_name,
433
+ self.operands[1].name,
434
+ self.operands[1].stack_offset,
435
+ self.operands[0].format("go"),
436
+ )
437
+ elif isinstance(self.operands[0], GeneralPurposeRegister64):
438
+ mov_name = {
439
+ (True, 1): "MOVBQSX",
440
+ (True, 2): "MOVWQSX",
441
+ (True, 4): "MOVLQSX",
442
+ (True, 8): "MOVQ",
443
+ (False, 1): "MOVBQZX",
444
+ (False, 2): "MOVWQZX",
445
+ (False, 4): "MOVLQZX",
446
+ (False, 8): "MOVQ",
447
+ }[(self.operands[1].is_signed_integer, self.operands[1].size)]
448
+ return text + "%s %s+%d(FP), %s" % (
449
+ mov_name,
450
+ self.operands[1].name,
451
+ self.operands[1].stack_offset,
452
+ self.operands[0].format("go"),
453
+ )
454
+ elif isinstance(self.operands[0], MMXRegister):
455
+ mov_name = {4: "MOVD", 8: "MOVQ"}[self.operands[1].size]
456
+ return text + "%s %s+%d(FP), %s" % (
457
+ mov_name,
458
+ self.operands[1].name,
459
+ self.operands[1].stack_offset,
460
+ self.operands[0].format("go"),
461
+ )
462
+ elif isinstance(self.operands[0], XMMRegister):
463
+ mov_name = {4: "MOVD", 8: "MOVQ"}[self.operands[1].size]
464
+ return text + "%s %s+%d(FP), %s" % (
465
+ mov_name,
466
+ self.operands[1].name,
467
+ self.operands[1].stack_offset,
468
+ self.operands[0].format("go"),
469
+ )
470
+ else:
471
+ return text + str(self)
472
+
473
+
474
+ class STORE:
475
+ class RESULT(Instruction):
476
+ def __init__(self, *args, **kwargs):
477
+ from nervapy.common.function import active_function
478
+ from nervapy.util import is_int16, is_int32
479
+ from nervapy.x86_64.abi import goasm_amd64_abi, goasm_amd64p32_abi
480
+ from nervapy.x86_64.registers import (GeneralPurposeRegister,
481
+ MMXRegister, XMMRegister,
482
+ YMMRegister)
483
+
484
+ origin = kwargs.get("origin")
485
+ prototype = kwargs.get("prototype")
486
+ if (
487
+ origin is None
488
+ and prototype is None
489
+ and nervapy.x86_64.options.get_debug_level() > 0
490
+ ):
491
+ origin = inspect.stack()
492
+ super(STORE.RESULT, self).__init__("STORE.RESULT", origin=origin)
493
+ self.operands = tuple(map(check_operand, args))
494
+ self.out_regs = (False,)
495
+ self.in_regs = (True,)
496
+ if len(self.operands) != 1:
497
+ raise SyntaxError('Instruction "STORE.RESULT" requires 1 operand')
498
+
499
+ target_function = active_function
500
+ destination_offset = None
501
+ if target_function is None:
502
+ target_function = kwargs.get("target_function")
503
+ assert target_function.abi in {goasm_amd64_abi, goasm_amd64p32_abi}
504
+ destination_offset = target_function.result_offset
505
+ if target_function.result_type is None:
506
+ raise ValueError("STORE.RESULT can't be used with void functions")
507
+ self.destination_type = target_function.result_type
508
+ self.destination_size = self.destination_type.size
509
+ # Will be updated during ABI binding (ABIFunction._lower_pseudoinstructions)
510
+ self.destination_offset = destination_offset
511
+
512
+ if isinstance(self.operands[0], GeneralPurposeRegister):
513
+ if self.operands[0].size != self.destination_size:
514
+ raise ValueError(
515
+ "Can not store result in register %s: size mismatch with return type %s"
516
+ % (str(self.operands[0]), str(self.destination_type))
517
+ )
518
+ elif isinstance(self.operands[0], MMXRegister):
519
+ if self.destination_size not in {4, 8}:
520
+ raise ValueError(
521
+ "Can not store result in register %s: size mismatch with return type %s"
522
+ % (str(self.operands[0]), str(self.destination_type))
523
+ )
524
+ elif isinstance(self.operands[0], XMMRegister):
525
+ if self.destination_size not in {4, 8}:
526
+ raise ValueError(
527
+ "Can not store result in register %s: size mismatch with return type %s"
528
+ % (str(self.operands[0]), str(self.destination_type))
529
+ )
530
+ elif isinstance(self.operands[0], YMMRegister):
531
+ raise ValueError(
532
+ "Can not store result in register %s: unsupported register type"
533
+ )
534
+ elif is_int32(self.operands[0]):
535
+ if not self.destination_type.is_integer:
536
+ raise ValueError(
537
+ "Can not store integer result %d: type mismatch with result type %s"
538
+ % (self.operands[0], str(self.destination_type))
539
+ )
540
+ if is_int16(self.operands[0]) and self.destination_size < 2:
541
+ raise ValueError(
542
+ "Can not store integer result %d: size mismatch with result type %s"
543
+ % (self.operands[0], str(self.destination_type))
544
+ )
545
+ if is_int32(self.operands[0]) and self.destination_size < 4:
546
+ raise ValueError(
547
+ "Can not store integer result %d: size mismatch with result type %s"
548
+ % (self.operands[0], str(self.destination_type))
549
+ )
550
+
551
+ if nervapy.stream.active_stream is not None:
552
+ nervapy.stream.active_stream.add_instruction(self)
553
+
554
+ def format(self, assembly_format, indent=False, line_number=None):
555
+ assert assembly_format in {
556
+ "peachpy",
557
+ "go",
558
+ }, "Supported assembly formats are 'peachpy' and 'go'"
559
+
560
+ text = "\t" if indent else ""
561
+ if assembly_format == "go":
562
+ from nervapy.x86_64.operand import format_operand
563
+ from nervapy.x86_64.registers import MMXRegister, XMMRegister
564
+
565
+ if isinstance(self.operands[0], MMXRegister):
566
+ mov_name = {4: "MOVD", 8: "MOVQ"}[self.destination_size]
567
+ elif isinstance(self.operands[0], XMMRegister):
568
+ if self.destination_type.is_floating_point:
569
+ mov_name = {4: "MOVSS", 8: "MOVSD"}[self.destination_size]
570
+ else:
571
+ mov_name = {4: "MOVD", 8: "MOVQ"}[self.destination_size]
572
+ else:
573
+ mov_name = {1: "MOVB", 2: "MOVW", 4: "MOVL", 8: "MOVQ"}[
574
+ self.destination_size
575
+ ]
576
+ return text + "%s %s, ret+%d(FP)" % (
577
+ mov_name,
578
+ format_operand(self.operands[0], "go"),
579
+ self.destination_offset,
580
+ )
581
+
582
+ else:
583
+ return text + str(self)
584
+
585
+
586
+ class SWAP:
587
+ @staticmethod
588
+ def REGISTERS(register_x, register_y):
589
+ from nervapy.x86_64.registers import Register
590
+
591
+ if isinstance(register_x, Register) and isinstance(register_y, Register):
592
+ if (
593
+ register_x.kind == register_y.kind
594
+ and register_x.size == register_y.size
595
+ ):
596
+ register_x.virtual_id, register_y.virtual_id = (
597
+ register_y.virtual_id,
598
+ register_x.virtual_id,
599
+ )
600
+ register_x.physical_id, register_y.physical_id = (
601
+ register_y.physical_id,
602
+ register_x.physical_id,
603
+ )
604
+ else:
605
+ raise ValueError(
606
+ "Registers {0} and {1} have incompatible register types".format(
607
+ register_x, register_y
608
+ )
609
+ )
610
+ else:
611
+ raise TypeError("Arguments must be of register regtype")
612
+
613
+
614
+ def REDUCE(reduction_instruction, registers):
615
+ if not isinstance(registers, (tuple, list)):
616
+ raise ValueError("List or tuple of registers expected")
617
+ offset = 1
618
+ while offset < len(registers):
619
+ for i in range(offset, len(registers), 2 * offset):
620
+ reduction_instruction(registers[i - offset], registers[i])
621
+ offset *= 2
622
+ return registers[0]
623
+
624
+
625
+ class IACA:
626
+
627
+ class START(Instruction):
628
+ def __init__(self, *args, **kwargs):
629
+ origin = kwargs.get("origin")
630
+ prototype = kwargs.get("prototype")
631
+ if (
632
+ origin is None
633
+ and prototype is None
634
+ and nervapy.x86_64.options.get_debug_level() > 0
635
+ ):
636
+ origin = inspect.stack()
637
+ super(IACA.START, self).__init__("IACA.START", origin=origin)
638
+
639
+ self.operands = tuple(map(check_operand, args))
640
+ if len(self.operands) == 0:
641
+ # It is not an error to return nothing from a function with a return type
642
+ self.in_regs = tuple()
643
+ self.out_regs = tuple()
644
+ self.out_operands = tuple()
645
+ self.encodings.append(
646
+ (
647
+ 0x0,
648
+ lambda op: bytearray(
649
+ [0x0F, 0x0B, 0xBB, 0x6F, 0x00, 0x00, 0x00, 0x64, 0x67, 0x90]
650
+ ),
651
+ )
652
+ )
653
+ else:
654
+ raise SyntaxError('Pseudo-instruction "IACA.START" requires 0 operands')
655
+ if nervapy.stream.active_stream is not None:
656
+ nervapy.stream.active_stream.add_instruction(self)
657
+
658
+ class END(Instruction):
659
+ def __init__(self, *args, **kwargs):
660
+ origin = kwargs.get("origin")
661
+ prototype = kwargs.get("prototype")
662
+ if (
663
+ origin is None
664
+ and prototype is None
665
+ and nervapy.x86_64.options.get_debug_level() > 0
666
+ ):
667
+ origin = inspect.stack()
668
+ super(IACA.END, self).__init__("IACA.END", origin=origin)
669
+
670
+ self.operands = tuple(map(check_operand, args))
671
+ if len(self.operands) == 0:
672
+ self.in_regs = tuple()
673
+ self.out_regs = tuple()
674
+ self.out_operands = tuple()
675
+ self.encodings.append(
676
+ (
677
+ 0x0,
678
+ lambda op: bytearray(
679
+ [0xBB, 0xDE, 0x00, 0x00, 0x00, 0x64, 0x67, 0x90, 0x0F, 0x0B]
680
+ ),
681
+ )
682
+ )
683
+ else:
684
+ raise SyntaxError('Pseudo-instruction "IACA.END" requires 0 operands')
685
+ if nervapy.stream.active_stream is not None:
686
+ nervapy.stream.active_stream.add_instruction(self)