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.
- 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 +2465 -0
- nervapy/arm/generic.py +10796 -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.7.dist-info/METADATA +310 -0
- pynerva-0.0.7.dist-info/RECORD +74 -0
- pynerva-0.0.7.dist-info/WHEEL +4 -0
- pynerva-0.0.7.dist-info/licenses/LICENSE.rst +15 -0
nervapy/arm/pseudo.py
ADDED
|
@@ -0,0 +1,652 @@
|
|
|
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
|
+
from nervapy.arm.instructions import Instruction, Operand, QuasiInstruction
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Label(object):
|
|
11
|
+
def __init__(self, name, is_external=False):
|
|
12
|
+
super(Label, self).__init__()
|
|
13
|
+
self.name = name
|
|
14
|
+
self.is_external = is_external
|
|
15
|
+
|
|
16
|
+
def __str__(self):
|
|
17
|
+
return "<LABEL:" + self.name + ">"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ExternalFunction(object):
|
|
21
|
+
"""Represents an external function that needs to be imported."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, name):
|
|
24
|
+
super(ExternalFunction, self).__init__()
|
|
25
|
+
self.name = name
|
|
26
|
+
|
|
27
|
+
def __str__(self):
|
|
28
|
+
return self.name
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class LabelQuasiInstruction(QuasiInstruction):
|
|
32
|
+
def __init__(self, name, origin=None):
|
|
33
|
+
super(LabelQuasiInstruction, self).__init__("<LABEL>", origin=origin)
|
|
34
|
+
if name.is_label():
|
|
35
|
+
self.name = name.label
|
|
36
|
+
else:
|
|
37
|
+
raise TypeError("Name must be an Label or string")
|
|
38
|
+
self.input_branches = set()
|
|
39
|
+
|
|
40
|
+
def __str__(self):
|
|
41
|
+
return "L" + self.name + ":"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class AlignQuasiInstruction(QuasiInstruction):
|
|
45
|
+
supported_alignments = [2, 4, 8, 16, 32]
|
|
46
|
+
|
|
47
|
+
def __init__(self, alignment, origin=None):
|
|
48
|
+
super(AlignQuasiInstruction, self).__init__("<ALIGN>", origin=origin)
|
|
49
|
+
if isinstance(alignment, int):
|
|
50
|
+
if alignment in AlignQuasiInstruction.supported_alignments:
|
|
51
|
+
self.alignment = alignment
|
|
52
|
+
else:
|
|
53
|
+
raise ValueError(
|
|
54
|
+
"The alignment value {0} is not in the list of supported alignments ({1})".format(
|
|
55
|
+
alignment, ", ".join(AlignQuasiInstruction.supported_alignments)
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
else:
|
|
59
|
+
raise TypeError("The alignment value must be an integer")
|
|
60
|
+
|
|
61
|
+
def __str__(self):
|
|
62
|
+
return "align {0}".format(self.alignment)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class LoadConstantPseudoInstruction(Instruction):
|
|
66
|
+
def __init__(self, destination, source, origin=None):
|
|
67
|
+
super(LoadConstantPseudoInstruction, self).__init__(
|
|
68
|
+
"<LOAD-CONSTANT>", origin=origin
|
|
69
|
+
)
|
|
70
|
+
if destination.is_register():
|
|
71
|
+
self.destination = destination
|
|
72
|
+
else:
|
|
73
|
+
raise ValueError(
|
|
74
|
+
"Load constant pseudo-instruction expects a register as a destination"
|
|
75
|
+
)
|
|
76
|
+
if source.is_constant():
|
|
77
|
+
if (
|
|
78
|
+
destination.register.size * 8
|
|
79
|
+
== source.constant.size * source.constant.repeats
|
|
80
|
+
):
|
|
81
|
+
self.source = source
|
|
82
|
+
elif (
|
|
83
|
+
destination.register.size == 16
|
|
84
|
+
and source.constant.size == 64
|
|
85
|
+
and source.constant.repeats == 1
|
|
86
|
+
and source.constant.basic_type == "float64"
|
|
87
|
+
):
|
|
88
|
+
self.source = source
|
|
89
|
+
elif (
|
|
90
|
+
destination.register.size == 16
|
|
91
|
+
and source.constant.size == 32
|
|
92
|
+
and source.constant.repeats == 1
|
|
93
|
+
and source.constant.basic_type == "float32"
|
|
94
|
+
):
|
|
95
|
+
self.source = source
|
|
96
|
+
else:
|
|
97
|
+
raise ValueError(
|
|
98
|
+
"The size of constant should be the same as the size of register"
|
|
99
|
+
)
|
|
100
|
+
else:
|
|
101
|
+
raise ValueError(
|
|
102
|
+
"Load constant pseudo-instruction expects a Constant instance as a source"
|
|
103
|
+
)
|
|
104
|
+
self.size = 4 + 4
|
|
105
|
+
|
|
106
|
+
def __str__(self):
|
|
107
|
+
return "LOAD.CONSTANT {0} = {1}".format(self.destination, self.source)
|
|
108
|
+
|
|
109
|
+
def get_input_registers_list(self):
|
|
110
|
+
return list()
|
|
111
|
+
|
|
112
|
+
def get_output_registers_list(self):
|
|
113
|
+
return [self.destination.register]
|
|
114
|
+
|
|
115
|
+
def get_constant(self):
|
|
116
|
+
return self.source.constant
|
|
117
|
+
|
|
118
|
+
def get_local_variable(self):
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class LoadArgumentPseudoInstruction(Instruction):
|
|
123
|
+
def __init__(self, destination, source, origin=None):
|
|
124
|
+
from nervapy import Argument, Yep32f, Yep64f
|
|
125
|
+
from nervapy.arm.function import active_function
|
|
126
|
+
|
|
127
|
+
super(LoadArgumentPseudoInstruction, self).__init__(
|
|
128
|
+
"<LOAD-PARAMETER>", [destination, source], origin=origin
|
|
129
|
+
)
|
|
130
|
+
if isinstance(source, Argument):
|
|
131
|
+
argument = active_function.find_argument(source)
|
|
132
|
+
if argument is not None:
|
|
133
|
+
self.argument = argument
|
|
134
|
+
else:
|
|
135
|
+
raise ValueError(
|
|
136
|
+
"{0} is not an argument of the active function".format(source)
|
|
137
|
+
)
|
|
138
|
+
else:
|
|
139
|
+
raise TypeError("LOAD.ARGUMENT expects an Argument object as a source")
|
|
140
|
+
if destination.is_general_purpose_register() and (
|
|
141
|
+
argument.is_integer or argument.is_pointer or argument.is_codeunit
|
|
142
|
+
):
|
|
143
|
+
if destination.register.size >= argument.size:
|
|
144
|
+
self.destination = destination
|
|
145
|
+
else:
|
|
146
|
+
raise ValueError(
|
|
147
|
+
"Destination register %s is too narrow for the argument %s"
|
|
148
|
+
% (destination, argument)
|
|
149
|
+
)
|
|
150
|
+
elif destination.is_s_register() and source.c_type == Yep32f:
|
|
151
|
+
self.destination = destination
|
|
152
|
+
elif destination.is_d_register() and source.c_type == Yep64f:
|
|
153
|
+
self.destination = destination
|
|
154
|
+
else:
|
|
155
|
+
raise ValueError("Unsupported combination of instruction operands")
|
|
156
|
+
|
|
157
|
+
def __str__(self):
|
|
158
|
+
return "LOAD.ARGUMENT {0} = {1}".format(self.destination, self.argument)
|
|
159
|
+
|
|
160
|
+
def get_input_registers_list(self):
|
|
161
|
+
from nervapy.arm.registers import sp
|
|
162
|
+
|
|
163
|
+
if self.argument.register:
|
|
164
|
+
return [self.argument.register]
|
|
165
|
+
else:
|
|
166
|
+
return [sp]
|
|
167
|
+
|
|
168
|
+
def get_output_registers_list(self):
|
|
169
|
+
return [self.destination.register]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class ReturnInstruction(QuasiInstruction):
|
|
173
|
+
def __init__(self, return_value=None, origin=None):
|
|
174
|
+
super(ReturnInstruction, self).__init__("RETURN", origin=origin)
|
|
175
|
+
if return_value.is_none():
|
|
176
|
+
self.return_value = None
|
|
177
|
+
elif return_value.is_modified_immediate12():
|
|
178
|
+
self.return_value = return_value.immediate
|
|
179
|
+
else:
|
|
180
|
+
raise ValueError(
|
|
181
|
+
"Return value is not representable as a 12-bit modified immediate integer"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def to_instruction_list(self):
|
|
185
|
+
from nervapy.arm.generic import BX, MOV
|
|
186
|
+
from nervapy.arm.registers import lr, r0
|
|
187
|
+
from nervapy.stream import InstructionStream
|
|
188
|
+
|
|
189
|
+
return_instructions = InstructionStream()
|
|
190
|
+
with return_instructions:
|
|
191
|
+
if self.return_value is None:
|
|
192
|
+
pass
|
|
193
|
+
else:
|
|
194
|
+
MOV(r0, self.return_value)
|
|
195
|
+
BX(lr)
|
|
196
|
+
return list(iter(return_instructions))
|
|
197
|
+
|
|
198
|
+
def __str__(self):
|
|
199
|
+
return "RETURN {0}".format(self.return_value)
|
|
200
|
+
|
|
201
|
+
def get_input_registers_list(self):
|
|
202
|
+
from nervapy.arm.registers import sp
|
|
203
|
+
|
|
204
|
+
return [sp]
|
|
205
|
+
|
|
206
|
+
def get_output_registers_list(self):
|
|
207
|
+
from nervapy.arm.registers import sp
|
|
208
|
+
|
|
209
|
+
return [sp]
|
|
210
|
+
|
|
211
|
+
def get_constant(self):
|
|
212
|
+
return None
|
|
213
|
+
|
|
214
|
+
def get_local_variable(self):
|
|
215
|
+
return None
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class AssumeInitializedPseudoInstruction(Instruction):
|
|
219
|
+
def __init__(self, destination, origin=None):
|
|
220
|
+
super(AssumeInitializedPseudoInstruction, self).__init__(
|
|
221
|
+
"<ASSUME-INITIALIZED>", origin=origin
|
|
222
|
+
)
|
|
223
|
+
if destination.is_register():
|
|
224
|
+
self.destination = destination
|
|
225
|
+
else:
|
|
226
|
+
raise ValueError(
|
|
227
|
+
"Assume initialized pseudo-instruction expects a register as a destination"
|
|
228
|
+
)
|
|
229
|
+
self.size = 0
|
|
230
|
+
|
|
231
|
+
def __str__(self):
|
|
232
|
+
return "ASSUME.INITIALIZED {0}".format(self.destination)
|
|
233
|
+
|
|
234
|
+
def get_input_registers_list(self):
|
|
235
|
+
return list()
|
|
236
|
+
|
|
237
|
+
def get_output_registers_list(self):
|
|
238
|
+
return [self.destination.register]
|
|
239
|
+
|
|
240
|
+
def get_constant(self):
|
|
241
|
+
return None
|
|
242
|
+
|
|
243
|
+
def get_local_variable(self):
|
|
244
|
+
return None
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def LABEL(name):
|
|
248
|
+
instruction = LabelQuasiInstruction(Operand(name))
|
|
249
|
+
if nervapy.stream.active_stream is not None:
|
|
250
|
+
nervapy.stream.active_stream.add_instruction(instruction)
|
|
251
|
+
return instruction
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class Loop:
|
|
255
|
+
def __init__(self, name=None):
|
|
256
|
+
if name is None:
|
|
257
|
+
import inspect
|
|
258
|
+
import re
|
|
259
|
+
|
|
260
|
+
source_line = inspect.stack()[1][4][0].strip()
|
|
261
|
+
match = re.match(
|
|
262
|
+
"(?:\\w+\\.)*(\\w+)\\s*=\\s*(?:\\w+\\.)*Loop\\(.*\\)", source_line
|
|
263
|
+
)
|
|
264
|
+
if match:
|
|
265
|
+
name = match.group(1)
|
|
266
|
+
else:
|
|
267
|
+
match = re.match(
|
|
268
|
+
"\\s*with\\s+(?:\\w+\\.)*Loop\\(.*\\)\\s+as\\s+(\\w+)\\s*:\\s*",
|
|
269
|
+
source_line,
|
|
270
|
+
)
|
|
271
|
+
if match:
|
|
272
|
+
name = match.group(1)
|
|
273
|
+
else:
|
|
274
|
+
raise ValueError("Loop name is unspecified")
|
|
275
|
+
self.name = name
|
|
276
|
+
self.begin = Label(self.name + "_begin")
|
|
277
|
+
self.end = Label(self.name + "_end")
|
|
278
|
+
|
|
279
|
+
def __enter__(self):
|
|
280
|
+
LABEL(self.begin)
|
|
281
|
+
return self
|
|
282
|
+
|
|
283
|
+
def __exit__(self, type, value, traceback):
|
|
284
|
+
if type is None:
|
|
285
|
+
LABEL(self.end)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def ALIGN(alignment):
|
|
289
|
+
instruction = AlignQuasiInstruction(alignment)
|
|
290
|
+
if nervapy.stream.active_stream is not None:
|
|
291
|
+
nervapy.stream.active_stream.add_instruction(instruction)
|
|
292
|
+
return instruction
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def RETURN(return_value=None):
|
|
296
|
+
instruction = ReturnInstruction(Operand(return_value))
|
|
297
|
+
if nervapy.stream.active_stream is not None:
|
|
298
|
+
nervapy.stream.active_stream.add_instruction(instruction)
|
|
299
|
+
return instruction
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
class LOAD:
|
|
303
|
+
@staticmethod
|
|
304
|
+
def CONSTANT(destination, source):
|
|
305
|
+
from nervapy.arm.function import active_function
|
|
306
|
+
|
|
307
|
+
origin = inspect.stack() if active_function.collect_origin else None
|
|
308
|
+
instruction = LoadConstantPseudoInstruction(
|
|
309
|
+
Operand(destination), Operand(source), origin=origin
|
|
310
|
+
)
|
|
311
|
+
if nervapy.stream.active_stream is not None:
|
|
312
|
+
nervapy.stream.active_stream.add_instruction(instruction)
|
|
313
|
+
return instruction
|
|
314
|
+
|
|
315
|
+
@staticmethod
|
|
316
|
+
def ARGUMENT(destination, source):
|
|
317
|
+
from nervapy.arm.function import active_function
|
|
318
|
+
|
|
319
|
+
origin = inspect.stack() if active_function.collect_origin else None
|
|
320
|
+
instruction = LoadArgumentPseudoInstruction(
|
|
321
|
+
Operand(destination), source, origin=origin
|
|
322
|
+
)
|
|
323
|
+
if nervapy.stream.active_stream is not None:
|
|
324
|
+
nervapy.stream.active_stream.add_instruction(instruction)
|
|
325
|
+
return instruction
|
|
326
|
+
|
|
327
|
+
@staticmethod
|
|
328
|
+
def ARGUMENTS():
|
|
329
|
+
from nervapy import Yep32f, Yep64f
|
|
330
|
+
from nervapy.arm.function import active_function
|
|
331
|
+
from nervapy.arm.registers import (DRegister, GeneralPurposeRegister,
|
|
332
|
+
SRegister)
|
|
333
|
+
|
|
334
|
+
registers = list()
|
|
335
|
+
for argument in active_function.arguments:
|
|
336
|
+
if argument.is_pointer or argument.is_integer or argument.is_codeunit:
|
|
337
|
+
if argument.size <= 4:
|
|
338
|
+
register = GeneralPurposeRegister()
|
|
339
|
+
LOAD.ARGUMENT(register, argument)
|
|
340
|
+
else:
|
|
341
|
+
raise NotImplementedError("TODO: Handle 8-byte integers")
|
|
342
|
+
elif argument.is_floating_point:
|
|
343
|
+
if argument.c_type == Yep32f:
|
|
344
|
+
register = SRegister()
|
|
345
|
+
LOAD.ARGUMENT(register, argument)
|
|
346
|
+
elif argument.c_type == Yep64f:
|
|
347
|
+
register = DRegister()
|
|
348
|
+
LOAD.ARGUMENT(register, argument)
|
|
349
|
+
else:
|
|
350
|
+
raise TypeError("Unknown floating-point type %s" % argument.c_type)
|
|
351
|
+
else:
|
|
352
|
+
raise TypeError("Unknown argument type %s" % argument.c_type)
|
|
353
|
+
registers.append(register)
|
|
354
|
+
return tuple(registers)
|
|
355
|
+
|
|
356
|
+
@staticmethod
|
|
357
|
+
def ZERO(destination, ctype):
|
|
358
|
+
if isinstance(ctype, nervapy.c.Type):
|
|
359
|
+
# if isinstance(destination, SRegister):
|
|
360
|
+
# PXOR( destination, destination )
|
|
361
|
+
# elif isinstance(destination, DRegister):
|
|
362
|
+
# if ctype.is_floating_point():
|
|
363
|
+
# if Target.has_avx():
|
|
364
|
+
# SIMD_XOR = {4: VXORPS, 8: VXORPD }[ctype.get_size()]
|
|
365
|
+
# else:
|
|
366
|
+
# SIMD_XOR = {4: XORPS, 8: XORPD}[ctype.get_size()]
|
|
367
|
+
# else:
|
|
368
|
+
# SIMD_XOR = VPXOR if Target.has_avx() else PXOR
|
|
369
|
+
# SIMD_XOR( destination, destination )
|
|
370
|
+
# elif isinstance(destination, QRegister):
|
|
371
|
+
# LOAD.ZERO( destination.get_oword(), ctype )
|
|
372
|
+
# else:
|
|
373
|
+
raise TypeError("Unsupported type of destination register")
|
|
374
|
+
else:
|
|
375
|
+
raise TypeError("Type must be a C type")
|
|
376
|
+
|
|
377
|
+
@staticmethod
|
|
378
|
+
def ELEMENT(destination, source, ctype, increment_pointer=False):
|
|
379
|
+
from nervapy import Type
|
|
380
|
+
from nervapy.arm.function import active_function
|
|
381
|
+
from nervapy.arm.generic import ADD, LDR, LDRB, LDRH, LDRSB, LDRSH
|
|
382
|
+
from nervapy.arm.instructions import Operand
|
|
383
|
+
from nervapy.arm.registers import (DRegister, GeneralPurposeRegister,
|
|
384
|
+
Register, SRegister)
|
|
385
|
+
from nervapy.arm.vfpneon import VLDR
|
|
386
|
+
|
|
387
|
+
if not isinstance(ctype, Type):
|
|
388
|
+
raise TypeError("Type must be a C type")
|
|
389
|
+
if isinstance(destination, Register):
|
|
390
|
+
raise TypeError("Destination must be a register")
|
|
391
|
+
if not Operand(source).is_memory_address():
|
|
392
|
+
raise TypeError("Source must be a memory operand")
|
|
393
|
+
memory_size = ctype.get_size(active_function.abi)
|
|
394
|
+
if isinstance(destination, GeneralPurposeRegister):
|
|
395
|
+
if ctype.is_unsigned_integer:
|
|
396
|
+
if memory_size == 4:
|
|
397
|
+
if increment_pointer:
|
|
398
|
+
LDR(destination, source, memory_size)
|
|
399
|
+
else:
|
|
400
|
+
LDR(destination, source)
|
|
401
|
+
elif memory_size == 2:
|
|
402
|
+
if increment_pointer:
|
|
403
|
+
LDRH(destination, source, memory_size)
|
|
404
|
+
else:
|
|
405
|
+
LDRH(destination, source)
|
|
406
|
+
elif memory_size == 1:
|
|
407
|
+
if increment_pointer:
|
|
408
|
+
LDRB(destination, source, memory_size)
|
|
409
|
+
else:
|
|
410
|
+
LDRB(destination, source)
|
|
411
|
+
else:
|
|
412
|
+
raise ValueError(
|
|
413
|
+
"Invalid memory operand size {0}".format(memory_size)
|
|
414
|
+
)
|
|
415
|
+
elif ctype.is_signed_integer:
|
|
416
|
+
if memory_size == 4:
|
|
417
|
+
if increment_pointer:
|
|
418
|
+
LDR(destination, source, memory_size)
|
|
419
|
+
else:
|
|
420
|
+
LDR(destination, source)
|
|
421
|
+
elif memory_size == 2:
|
|
422
|
+
if increment_pointer:
|
|
423
|
+
LDRSH(destination, source, memory_size)
|
|
424
|
+
else:
|
|
425
|
+
LDRSH(destination, source)
|
|
426
|
+
elif memory_size == 1:
|
|
427
|
+
if increment_pointer:
|
|
428
|
+
LDRSB(destination, source, memory_size)
|
|
429
|
+
else:
|
|
430
|
+
LDRSB(destination, source)
|
|
431
|
+
else:
|
|
432
|
+
raise ValueError(
|
|
433
|
+
"Invalid memory operand size {0}".format(memory_size)
|
|
434
|
+
)
|
|
435
|
+
else:
|
|
436
|
+
raise TypeError("Invalid memory operand type")
|
|
437
|
+
elif isinstance(destination, SRegister):
|
|
438
|
+
if ctype.is_floating_point:
|
|
439
|
+
if memory_size == 4:
|
|
440
|
+
VLDR(destination, source)
|
|
441
|
+
if increment_pointer:
|
|
442
|
+
address_register = Operand(source).get_registers_list()[0]
|
|
443
|
+
ADD(address_register, memory_size)
|
|
444
|
+
else:
|
|
445
|
+
raise ValueError(
|
|
446
|
+
"Invalid memory operand size {0}".format(memory_size)
|
|
447
|
+
)
|
|
448
|
+
else:
|
|
449
|
+
raise TypeError("Invalid memory operand type")
|
|
450
|
+
elif isinstance(destination, DRegister):
|
|
451
|
+
if ctype.is_floating_point:
|
|
452
|
+
if memory_size == 8:
|
|
453
|
+
VLDR(destination, source)
|
|
454
|
+
if increment_pointer:
|
|
455
|
+
address_register = Operand(source).get_registers_list()[0]
|
|
456
|
+
ADD(address_register, memory_size)
|
|
457
|
+
else:
|
|
458
|
+
raise ValueError(
|
|
459
|
+
"Invalid memory operand size {0}".format(memory_size)
|
|
460
|
+
)
|
|
461
|
+
else:
|
|
462
|
+
raise TypeError("Invalid memory operand type")
|
|
463
|
+
else:
|
|
464
|
+
raise TypeError("Unsupported destination type")
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
class STORE:
|
|
468
|
+
@staticmethod
|
|
469
|
+
def ELEMENT(destination, source, ctype, increment_pointer=False):
|
|
470
|
+
from nervapy.arm.function import active_function
|
|
471
|
+
from nervapy.arm.generic import ADD, STR, STRB, STRH
|
|
472
|
+
from nervapy.arm.instructions import Operand
|
|
473
|
+
from nervapy.arm.registers import (DRegister, GeneralPurposeRegister,
|
|
474
|
+
SRegister)
|
|
475
|
+
from nervapy.arm.vfpneon import VSTR
|
|
476
|
+
|
|
477
|
+
if isinstance(ctype, nervapy.c.Type):
|
|
478
|
+
if Operand(destination).is_memory_address():
|
|
479
|
+
if Operand(source).is_register():
|
|
480
|
+
memory_size = ctype.get_size(active_function.abi)
|
|
481
|
+
if isinstance(source, GeneralPurposeRegister):
|
|
482
|
+
if ctype.is_integer():
|
|
483
|
+
if memory_size == 4:
|
|
484
|
+
if increment_pointer:
|
|
485
|
+
STR(source, destination, memory_size)
|
|
486
|
+
else:
|
|
487
|
+
STR(source, destination)
|
|
488
|
+
elif memory_size == 2:
|
|
489
|
+
if increment_pointer:
|
|
490
|
+
STRH(source, destination, memory_size)
|
|
491
|
+
else:
|
|
492
|
+
STRH(source, destination)
|
|
493
|
+
elif memory_size == 1:
|
|
494
|
+
if increment_pointer:
|
|
495
|
+
STRB(source, destination, memory_size)
|
|
496
|
+
else:
|
|
497
|
+
STRB(source, destination)
|
|
498
|
+
else:
|
|
499
|
+
raise ValueError(
|
|
500
|
+
"Invalid memory operand size {0}".format(
|
|
501
|
+
memory_size
|
|
502
|
+
)
|
|
503
|
+
)
|
|
504
|
+
else:
|
|
505
|
+
raise TypeError("Invalid memory operand type")
|
|
506
|
+
elif isinstance(source, SRegister):
|
|
507
|
+
if ctype.is_floating_point():
|
|
508
|
+
if memory_size == 4:
|
|
509
|
+
VSTR(source, destination)
|
|
510
|
+
if increment_pointer:
|
|
511
|
+
address_register = Operand(
|
|
512
|
+
destination
|
|
513
|
+
).get_registers_list()[0]
|
|
514
|
+
ADD(address_register, memory_size)
|
|
515
|
+
else:
|
|
516
|
+
raise ValueError(
|
|
517
|
+
"Invalid memory operand size {0}".format(
|
|
518
|
+
memory_size
|
|
519
|
+
)
|
|
520
|
+
)
|
|
521
|
+
else:
|
|
522
|
+
raise TypeError("Invalid memory operand type")
|
|
523
|
+
elif isinstance(source, DRegister):
|
|
524
|
+
if ctype.is_floating_point():
|
|
525
|
+
if memory_size == 8:
|
|
526
|
+
VSTR(source, destination)
|
|
527
|
+
if increment_pointer:
|
|
528
|
+
address_register = Operand(
|
|
529
|
+
destination
|
|
530
|
+
).get_registers_list()[0]
|
|
531
|
+
ADD(address_register, memory_size)
|
|
532
|
+
else:
|
|
533
|
+
raise ValueError(
|
|
534
|
+
"Invalid memory operand size {0}".format(
|
|
535
|
+
memory_size
|
|
536
|
+
)
|
|
537
|
+
)
|
|
538
|
+
else:
|
|
539
|
+
raise TypeError("Invalid memory operand type")
|
|
540
|
+
else:
|
|
541
|
+
raise TypeError("Source must be a general-purpose register")
|
|
542
|
+
else:
|
|
543
|
+
raise TypeError("Source must be a register")
|
|
544
|
+
else:
|
|
545
|
+
raise TypeError("Destination must be a memory operand")
|
|
546
|
+
else:
|
|
547
|
+
raise TypeError("Type must be a C type")
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
class ASSUME:
|
|
551
|
+
@staticmethod
|
|
552
|
+
def INITIALIZED(destination):
|
|
553
|
+
from nervapy.arm.function import active_function
|
|
554
|
+
|
|
555
|
+
origin = inspect.stack() if active_function.collect_origin else None
|
|
556
|
+
instruction = AssumeInitializedPseudoInstruction(
|
|
557
|
+
Operand(destination), origin=origin
|
|
558
|
+
)
|
|
559
|
+
if nervapy.stream.active_stream is not None:
|
|
560
|
+
nervapy.stream.active_stream.add_instruction(instruction)
|
|
561
|
+
return instruction
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
class IMPORT:
|
|
565
|
+
"""Declare external functions for ARMCC assembly."""
|
|
566
|
+
|
|
567
|
+
@staticmethod
|
|
568
|
+
def FUNCTION(name):
|
|
569
|
+
"""
|
|
570
|
+
Declare an external function that will be called.
|
|
571
|
+
For ARMCC, this generates an IMPORT directive.
|
|
572
|
+
|
|
573
|
+
Args:
|
|
574
|
+
name: Name of the external function (string or ExternalFunction)
|
|
575
|
+
|
|
576
|
+
Returns:
|
|
577
|
+
ExternalFunction object that can be used with BL
|
|
578
|
+
"""
|
|
579
|
+
from nervapy.arm.function import active_function
|
|
580
|
+
|
|
581
|
+
if isinstance(name, str):
|
|
582
|
+
external_func = ExternalFunction(name)
|
|
583
|
+
elif isinstance(name, ExternalFunction):
|
|
584
|
+
external_func = name
|
|
585
|
+
else:
|
|
586
|
+
raise TypeError("Function name must be a string or ExternalFunction")
|
|
587
|
+
|
|
588
|
+
# Register the external function with the active function
|
|
589
|
+
if active_function is not None:
|
|
590
|
+
if not hasattr(active_function, "external_functions"):
|
|
591
|
+
active_function.external_functions = set()
|
|
592
|
+
active_function.external_functions.add(external_func.name)
|
|
593
|
+
|
|
594
|
+
return external_func
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
class INIT:
|
|
598
|
+
@staticmethod
|
|
599
|
+
def ONCE(register_class, constant, register=None):
|
|
600
|
+
if register is None:
|
|
601
|
+
origin = (
|
|
602
|
+
inspect.stack()
|
|
603
|
+
if nervapy.arm.function.active_function.collect_origin
|
|
604
|
+
else None
|
|
605
|
+
)
|
|
606
|
+
register = register_class()
|
|
607
|
+
instruction = LoadConstantPseudoInstruction(
|
|
608
|
+
Operand(register), Operand(constant), origin=origin
|
|
609
|
+
)
|
|
610
|
+
if nervapy.stream.active_stream is not None:
|
|
611
|
+
nervapy.stream.active_stream.add_instruction(instruction)
|
|
612
|
+
return register
|
|
613
|
+
else:
|
|
614
|
+
return register
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
class REDUCE:
|
|
618
|
+
@staticmethod
|
|
619
|
+
def SUM(acc, input_type, output_type):
|
|
620
|
+
raise NotImplementedError("Needs ARM implementation")
|
|
621
|
+
|
|
622
|
+
@staticmethod
|
|
623
|
+
def MAX(acc, input_type, output_type):
|
|
624
|
+
raise NotImplementedError("Needs ARM implementation")
|
|
625
|
+
|
|
626
|
+
@staticmethod
|
|
627
|
+
def MIN(acc, input_type, output_type):
|
|
628
|
+
raise NotImplementedError("Needs ARM implementation")
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
class SWAP:
|
|
632
|
+
@staticmethod
|
|
633
|
+
def REGISTERS(register_x, register_y):
|
|
634
|
+
from nervapy.arm.registers import Register
|
|
635
|
+
|
|
636
|
+
if isinstance(register_x, Register) and isinstance(register_y, Register):
|
|
637
|
+
if (
|
|
638
|
+
register_x.type == register_y.type
|
|
639
|
+
and register_x.size == register_y.size
|
|
640
|
+
):
|
|
641
|
+
register_x.number, register_y.number = (
|
|
642
|
+
register_y.number,
|
|
643
|
+
register_x.number,
|
|
644
|
+
)
|
|
645
|
+
else:
|
|
646
|
+
raise ValueError(
|
|
647
|
+
"Registers {0} and {1} have incompatible register types".format(
|
|
648
|
+
register_x, register_y
|
|
649
|
+
)
|
|
650
|
+
)
|
|
651
|
+
else:
|
|
652
|
+
raise TypeError("Arguments must be of register type")
|