fprime-gds 4.0.2a2__py3-none-any.whl → 4.0.2a4__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.
- fprime_gds/common/distributor/distributor.py +9 -6
- fprime_gds/common/fpy/README.md +190 -42
- fprime_gds/common/fpy/SPEC.md +153 -39
- fprime_gds/common/fpy/bytecode/assembler.py +62 -0
- fprime_gds/common/fpy/bytecode/directives.py +620 -294
- fprime_gds/common/fpy/codegen.py +687 -910
- fprime_gds/common/fpy/grammar.lark +44 -9
- fprime_gds/common/fpy/main.py +27 -4
- fprime_gds/common/fpy/model.py +799 -0
- fprime_gds/common/fpy/parser.py +29 -34
- fprime_gds/common/fpy/test_helpers.py +119 -0
- fprime_gds/common/fpy/types.py +563 -0
- fprime_gds/common/models/dictionaries.py +23 -0
- fprime_gds/common/pipeline/standard.py +5 -0
- fprime_gds/common/testing_fw/api.py +8 -1
- fprime_gds/executables/cli.py +9 -0
- fprime_gds/executables/run_deployment.py +2 -0
- fprime_gds/flask/app.py +17 -2
- fprime_gds/flask/default_settings.py +1 -0
- fprime_gds/flask/static/index.html +7 -4
- fprime_gds/flask/static/js/config.js +9 -1
- fprime_gds/flask/static/js/vue-support/channel.js +16 -0
- fprime_gds/flask/static/js/vue-support/event.js +1 -0
- fprime_gds/flask/static/js/vue-support/fp-row.js +25 -1
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/METADATA +1 -1
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/RECORD +31 -27
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/entry_points.txt +2 -1
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/WHEEL +0 -0
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/licenses/LICENSE.txt +0 -0
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/licenses/NOTICE.txt +0 -0
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,799 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from enum import Enum
|
3
|
+
import inspect
|
4
|
+
import math
|
5
|
+
import struct
|
6
|
+
import typing
|
7
|
+
from fprime_gds.common.fpy.bytecode.directives import (
|
8
|
+
AllocateDirective,
|
9
|
+
AndDirective,
|
10
|
+
ConstCmdDirective,
|
11
|
+
Directive,
|
12
|
+
ExitDirective,
|
13
|
+
FloatAddDirective,
|
14
|
+
FloatDivideDirective,
|
15
|
+
FloatExponentDirective,
|
16
|
+
FloatFloorDivideDirective,
|
17
|
+
FloatModuloDirective,
|
18
|
+
FloatMultiplyDirective,
|
19
|
+
FloatSubtractDirective,
|
20
|
+
GotoDirective,
|
21
|
+
MemCompareDirective,
|
22
|
+
SignedIntDivideDirective,
|
23
|
+
SignedModuloDirective,
|
24
|
+
UnsignedIntDivideDirective,
|
25
|
+
IntMultiplyDirective,
|
26
|
+
FloatLogDirective,
|
27
|
+
DiscardDirective,
|
28
|
+
StackCmdDirective,
|
29
|
+
StorePrmDirective,
|
30
|
+
StoreTlmValDirective,
|
31
|
+
IfDirective,
|
32
|
+
IntAddDirective,
|
33
|
+
IntEqualDirective,
|
34
|
+
IntNotEqualDirective,
|
35
|
+
IntSubtractDirective,
|
36
|
+
LoadDirective,
|
37
|
+
NoOpDirective,
|
38
|
+
NotDirective,
|
39
|
+
OrDirective,
|
40
|
+
PushValDirective,
|
41
|
+
StoreDirective,
|
42
|
+
UnsignedLessThanDirective,
|
43
|
+
UnsignedLessThanOrEqualDirective,
|
44
|
+
UnsignedGreaterThanDirective,
|
45
|
+
UnsignedGreaterThanOrEqualDirective,
|
46
|
+
SignedGreaterThanDirective,
|
47
|
+
SignedGreaterThanOrEqualDirective,
|
48
|
+
SignedIntToFloatDirective,
|
49
|
+
SignedLessThanDirective,
|
50
|
+
SignedLessThanOrEqualDirective,
|
51
|
+
UnsignedIntToFloatDirective,
|
52
|
+
FloatEqualDirective,
|
53
|
+
FloatExtendDirective,
|
54
|
+
FloatGreaterThanDirective,
|
55
|
+
FloatGreaterThanOrEqualDirective,
|
56
|
+
FloatLessThanDirective,
|
57
|
+
FloatLessThanOrEqualDirective,
|
58
|
+
FloatNotEqualDirective,
|
59
|
+
FloatToSignedIntDirective,
|
60
|
+
FloatToUnsignedIntDirective,
|
61
|
+
FloatTruncateDirective,
|
62
|
+
UnsignedModuloDirective,
|
63
|
+
WaitAbsDirective,
|
64
|
+
WaitRelDirective,
|
65
|
+
IntegerZeroExtend16To64Directive,
|
66
|
+
IntegerZeroExtend32To64Directive,
|
67
|
+
IntegerZeroExtend8To64Directive,
|
68
|
+
IntegerSignedExtend16To64Directive,
|
69
|
+
IntegerSignedExtend32To64Directive,
|
70
|
+
IntegerSignedExtend8To64Directive,
|
71
|
+
IntegerTruncate64To16Directive,
|
72
|
+
IntegerTruncate64To32Directive,
|
73
|
+
IntegerTruncate64To8Directive
|
74
|
+
)
|
75
|
+
|
76
|
+
debug = True
|
77
|
+
|
78
|
+
WORD_SIZE = 8
|
79
|
+
# store return addr and prev stack frame offset in stack frame header
|
80
|
+
STACK_FRAME_HEADER_SIZE = 2 * WORD_SIZE
|
81
|
+
MAX_INT64 = 2**63 - 1
|
82
|
+
MIN_INT64 = -(2**63)
|
83
|
+
MASK_64_BIT = 2**64 - 1
|
84
|
+
|
85
|
+
|
86
|
+
def overflow_check(val: int) -> int:
|
87
|
+
masked_val = val & MASK_64_BIT
|
88
|
+
if masked_val > MAX_INT64:
|
89
|
+
return masked_val - 2**64
|
90
|
+
return masked_val
|
91
|
+
|
92
|
+
|
93
|
+
class DirectiveErrorCode(Enum):
|
94
|
+
NO_ERROR = 0
|
95
|
+
DIR_OUT_OF_BOUNDS = 1
|
96
|
+
TLM_GET_NOT_CONNECTED = 2
|
97
|
+
TLM_NOT_FOUND = 3
|
98
|
+
TLM_ACCESS_OUT_OF_BOUNDS = 4
|
99
|
+
PRM_GET_NOT_CONNECTED = 5
|
100
|
+
PRM_NOT_FOUND = 6
|
101
|
+
PRM_ACCESS_OUT_OF_BOUNDS = 7
|
102
|
+
CMD_SERIALIZE_FAILURE = 8
|
103
|
+
DELIBERATE_FAILURE = 9
|
104
|
+
STACK_OVERFLOW = 10
|
105
|
+
STACK_UNDERFLOW = 11
|
106
|
+
INVALID_ARGUMENT = 12
|
107
|
+
DIVIDE_BY_ZERO = 13
|
108
|
+
|
109
|
+
|
110
|
+
class FpySequencerModel:
|
111
|
+
|
112
|
+
def __init__(self, stack_size=4096) -> None:
|
113
|
+
self.stack = bytearray()
|
114
|
+
self.max_stack_size = stack_size
|
115
|
+
self.stack_frame_start = 0
|
116
|
+
|
117
|
+
self.dirs: list[Directive] = None
|
118
|
+
self.next_dir_idx = 0
|
119
|
+
self.tlm_db: dict[int, bytearray] = {}
|
120
|
+
self.prm_db: dict[int, bytearray] = {}
|
121
|
+
|
122
|
+
def reset(self):
|
123
|
+
self.stack = bytearray()
|
124
|
+
self.stack_frame_start = 0
|
125
|
+
|
126
|
+
self.dirs: list[Directive] = None
|
127
|
+
self.next_dir_idx = 0
|
128
|
+
self.tlm_db: dict[int, bytearray] = {}
|
129
|
+
self.prm_db: dict[int, bytearray] = {}
|
130
|
+
|
131
|
+
def dispatch(self, dir: Directive) -> DirectiveErrorCode:
|
132
|
+
opcode = dir.opcode
|
133
|
+
opcode_name = opcode.name
|
134
|
+
|
135
|
+
handler_fn = None
|
136
|
+
for name, func in inspect.getmembers(type(self), inspect.isfunction):
|
137
|
+
if not name.startswith("handle"):
|
138
|
+
# not a dir handler
|
139
|
+
continue
|
140
|
+
signature = inspect.signature(func)
|
141
|
+
params = list(signature.parameters.values())
|
142
|
+
assert len(params) == 2
|
143
|
+
assert params[1].annotation is not None
|
144
|
+
annotations = typing.get_type_hints(func)
|
145
|
+
param_type = annotations[params[1].name]
|
146
|
+
if isinstance(dir, param_type):
|
147
|
+
handler_fn = func
|
148
|
+
break
|
149
|
+
|
150
|
+
if handler_fn is None:
|
151
|
+
raise NotImplementedError(opcode_name + " not implemented")
|
152
|
+
|
153
|
+
# otherwise call the handler
|
154
|
+
ret = handler_fn(self, dir)
|
155
|
+
if ret is None:
|
156
|
+
return DirectiveErrorCode.NO_ERROR
|
157
|
+
return ret
|
158
|
+
|
159
|
+
def run(self, dirs: list[Directive], tlm: dict[int, bytearray] = None):
|
160
|
+
if tlm is None:
|
161
|
+
tlm = {}
|
162
|
+
self.reset()
|
163
|
+
self.dirs = dirs
|
164
|
+
self.tlm_db = tlm
|
165
|
+
if debug:
|
166
|
+
# begin the sequence at dir 0
|
167
|
+
print("stack", len(self.stack))
|
168
|
+
for byte in range(0, len(self.stack)):
|
169
|
+
|
170
|
+
print(
|
171
|
+
type(self.stack[byte]),
|
172
|
+
end=" ",
|
173
|
+
)
|
174
|
+
print()
|
175
|
+
while self.next_dir_idx < len(self.dirs):
|
176
|
+
next_dir = self.dirs[self.next_dir_idx]
|
177
|
+
if debug:
|
178
|
+
print(f"{self.next_dir_idx}:", next_dir)
|
179
|
+
self.next_dir_idx += 1
|
180
|
+
result = self.dispatch(next_dir)
|
181
|
+
if result != DirectiveErrorCode.NO_ERROR:
|
182
|
+
return result
|
183
|
+
if debug:
|
184
|
+
print("stack", len(self.stack))
|
185
|
+
for byte in range(0, len(self.stack)):
|
186
|
+
|
187
|
+
print(
|
188
|
+
self.stack[byte],
|
189
|
+
end=" ",
|
190
|
+
)
|
191
|
+
print()
|
192
|
+
return DirectiveErrorCode.NO_ERROR
|
193
|
+
|
194
|
+
def get_int_fmt_str(self, size: int, signed: bool) -> str:
|
195
|
+
fmt_char = None
|
196
|
+
if size == 1:
|
197
|
+
fmt_char = "b"
|
198
|
+
elif size == 2:
|
199
|
+
fmt_char = "h"
|
200
|
+
elif size == 4:
|
201
|
+
fmt_char = "i"
|
202
|
+
elif size == 8:
|
203
|
+
fmt_char = "q"
|
204
|
+
else:
|
205
|
+
assert False, size
|
206
|
+
if not signed:
|
207
|
+
fmt_char = fmt_char.upper()
|
208
|
+
|
209
|
+
return ">" + fmt_char
|
210
|
+
|
211
|
+
def push(
|
212
|
+
self, val: int | float | bytes | bytearray | bool, signed=True, size=WORD_SIZE
|
213
|
+
):
|
214
|
+
if isinstance(val, (bytes, bytearray)):
|
215
|
+
self.stack += val
|
216
|
+
elif isinstance(val, bool):
|
217
|
+
# push a byte onto stack
|
218
|
+
self.push(b"\xff" if val else b"\x00")
|
219
|
+
elif isinstance(val, float):
|
220
|
+
self.push(struct.pack(">d", val))
|
221
|
+
else:
|
222
|
+
assert isinstance(val, int), val
|
223
|
+
# first convert the int into bits
|
224
|
+
# have to do some stupid python stuff to deal with negatives
|
225
|
+
if val < 0:
|
226
|
+
# this should give us the right bit repr for two's complement
|
227
|
+
val = val + (1 << (size * 8))
|
228
|
+
|
229
|
+
bits = bin(val)[2:] # remove "0b"
|
230
|
+
# okay now truncate if necessary
|
231
|
+
bits = bits[-(size * 8) :]
|
232
|
+
self.stack += int(bits, 2).to_bytes(size, byteorder="big", signed=False)
|
233
|
+
|
234
|
+
def pop(self, type=int, signed=True, size=WORD_SIZE) -> int | float | bytearray:
|
235
|
+
"""pops one word off the stack and interprets it as an int or float, of
|
236
|
+
the specified signedness (if applicable) and bit width (if applicable)"""
|
237
|
+
value = self.stack[-size:]
|
238
|
+
self.stack = self.stack[:-size]
|
239
|
+
if type == int:
|
240
|
+
fmt_str = self.get_int_fmt_str(size, signed)
|
241
|
+
return struct.unpack(fmt_str, value)[0]
|
242
|
+
elif type == float:
|
243
|
+
if size == 8:
|
244
|
+
return struct.unpack(">d", value)[0]
|
245
|
+
assert size == 4, size
|
246
|
+
return struct.unpack(">f", value)[0]
|
247
|
+
elif type == bytes or type == bytearray:
|
248
|
+
# compiler knows best. always let them have the last word ;)
|
249
|
+
return value
|
250
|
+
elif type == bool:
|
251
|
+
assert size == 1, size
|
252
|
+
return bool(value[0])
|
253
|
+
else:
|
254
|
+
assert False, type
|
255
|
+
|
256
|
+
def handle_allocate_stack(self, dir: AllocateDirective):
|
257
|
+
if len(self.stack) + dir.size > self.max_stack_size:
|
258
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
259
|
+
|
260
|
+
self.stack += bytearray(0 for i in range(0, dir.size))
|
261
|
+
|
262
|
+
def handle_no_op(self, dir: NoOpDirective):
|
263
|
+
pass
|
264
|
+
|
265
|
+
def handle_pop_discard(self, dir: DiscardDirective):
|
266
|
+
if len(self.stack) < WORD_SIZE:
|
267
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
268
|
+
self.pop(size=dir.size, type=bytes)
|
269
|
+
|
270
|
+
def handle_load(self, dir: LoadDirective):
|
271
|
+
if len(self.stack) + dir.size > self.max_stack_size:
|
272
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
273
|
+
|
274
|
+
if dir.lvar_offset + self.stack_frame_start + dir.size > len(self.stack):
|
275
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
276
|
+
|
277
|
+
# grab a word beginning at lvar start and put on operand stack
|
278
|
+
value = self.stack[
|
279
|
+
self.stack_frame_start
|
280
|
+
+ dir.lvar_offset : (self.stack_frame_start + dir.lvar_offset + dir.size)
|
281
|
+
]
|
282
|
+
self.push(value)
|
283
|
+
|
284
|
+
def handle_store(self, dir: StoreDirective):
|
285
|
+
if len(self.stack) < dir.size:
|
286
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
287
|
+
|
288
|
+
if dir.lvar_offset + self.stack_frame_start + dir.size > len(self.stack):
|
289
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
290
|
+
|
291
|
+
# get the last `dir.size` bytes of the stack
|
292
|
+
value = self.stack[-dir.size :]
|
293
|
+
# remove them from top of stack
|
294
|
+
self.stack = self.stack[: -dir.size]
|
295
|
+
# put into lvar array at the given offset
|
296
|
+
for i in range(0, len(value)):
|
297
|
+
self.stack[dir.lvar_offset + self.stack_frame_start + i] = value[i]
|
298
|
+
|
299
|
+
def handle_push_val(self, dir: PushValDirective):
|
300
|
+
if len(self.stack) + WORD_SIZE > self.max_stack_size:
|
301
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
302
|
+
self.push(dir.val)
|
303
|
+
|
304
|
+
def handle_wait_rel(self, dir: WaitRelDirective):
|
305
|
+
if len(self.stack) < 8:
|
306
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
307
|
+
|
308
|
+
seconds = self.pop(type=float)
|
309
|
+
|
310
|
+
print("wait rel", seconds)
|
311
|
+
|
312
|
+
def handle_wait_abs(self, dir: WaitAbsDirective):
|
313
|
+
if len(self.stack) < 11:
|
314
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
315
|
+
useconds = self.pop(size=4)
|
316
|
+
seconds = self.pop(size=4)
|
317
|
+
time_context = self.pop(size=1)
|
318
|
+
time_base = self.pop(size=2)
|
319
|
+
|
320
|
+
print("wait abs", time_context, time_base, seconds, useconds)
|
321
|
+
|
322
|
+
def handle_const_cmd(self, dir: ConstCmdDirective):
|
323
|
+
print("cmd opcode", dir.cmd_opcode, "args", dir.args)
|
324
|
+
# always push CmdResponse.OK
|
325
|
+
self.push(0, size=4)
|
326
|
+
|
327
|
+
def handle_stack_cmd(self, dir: StackCmdDirective):
|
328
|
+
if len(self.stack) < dir.args_size + 4:
|
329
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
330
|
+
|
331
|
+
cmd = self.stack[-(dir.args_size + 4) :]
|
332
|
+
self.stack = self.stack[: -(dir.args_size + 4)]
|
333
|
+
|
334
|
+
print(
|
335
|
+
"cmd opcode",
|
336
|
+
int.from_bytes(cmd[-4:], signed=False, byteorder="big"),
|
337
|
+
"args",
|
338
|
+
cmd[:-4],
|
339
|
+
)
|
340
|
+
# always push CmdResponse.OK
|
341
|
+
self.push(0, size=4)
|
342
|
+
|
343
|
+
def handle_goto(self, dir: GotoDirective):
|
344
|
+
if dir.dir_idx > len(self.dirs):
|
345
|
+
return DirectiveErrorCode.DIR_OUT_OF_BOUNDS
|
346
|
+
self.next_dir_idx = dir.dir_idx
|
347
|
+
|
348
|
+
def handle_if(self, dir: IfDirective):
|
349
|
+
if dir.false_goto_dir_index > len(self.dirs):
|
350
|
+
return DirectiveErrorCode.DIR_OUT_OF_BOUNDS
|
351
|
+
if len(self.stack) < 1:
|
352
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
353
|
+
conditional = self.pop(type=bool, size=1)
|
354
|
+
if not conditional:
|
355
|
+
self.next_dir_idx = dir.false_goto_dir_index
|
356
|
+
|
357
|
+
def handle_store_tlm_val(self, dir: StoreTlmValDirective):
|
358
|
+
whole_value: bytearray = self.tlm_db.get(dir.chan_id, None)
|
359
|
+
if whole_value is None:
|
360
|
+
return DirectiveErrorCode.TLM_NOT_FOUND
|
361
|
+
|
362
|
+
if (
|
363
|
+
self.stack_frame_start + dir.lvar_offset + len(whole_value)
|
364
|
+
> self.max_stack_size
|
365
|
+
):
|
366
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
367
|
+
|
368
|
+
self.stack[
|
369
|
+
self.stack_frame_start
|
370
|
+
+ dir.lvar_offset : (
|
371
|
+
self.stack_frame_start + dir.lvar_offset + len(whole_value)
|
372
|
+
)
|
373
|
+
] = whole_value
|
374
|
+
|
375
|
+
def handle_store_prm(self, dir: StorePrmDirective):
|
376
|
+
whole_value: bytearray = self.prm_db.get(dir.prm_id, None)
|
377
|
+
if whole_value is None:
|
378
|
+
return DirectiveErrorCode.PRM_NOT_FOUND
|
379
|
+
|
380
|
+
if (
|
381
|
+
self.stack_frame_start + dir.lvar_offset + len(whole_value)
|
382
|
+
> self.max_stack_size
|
383
|
+
):
|
384
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
385
|
+
|
386
|
+
self.stack[
|
387
|
+
self.stack_frame_start
|
388
|
+
+ dir.lvar_offset : (
|
389
|
+
self.stack_frame_start + dir.lvar_offset + len(whole_value)
|
390
|
+
)
|
391
|
+
] = whole_value
|
392
|
+
|
393
|
+
def handle_or(self, dir: OrDirective):
|
394
|
+
if len(self.stack) < 2:
|
395
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
396
|
+
rhs = self.pop(type=bool, size=1)
|
397
|
+
lhs = self.pop(type=bool, size=1)
|
398
|
+
self.push(lhs or rhs)
|
399
|
+
|
400
|
+
def handle_and(self, dir: AndDirective):
|
401
|
+
if len(self.stack) < 2:
|
402
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
403
|
+
rhs = self.pop(type=bool, size=1)
|
404
|
+
lhs = self.pop(type=bool, size=1)
|
405
|
+
self.push(lhs and rhs)
|
406
|
+
|
407
|
+
def handle_ieq(self, dir: IntEqualDirective):
|
408
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
409
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
410
|
+
self.push(self.pop() == self.pop())
|
411
|
+
|
412
|
+
def handle_ine(self, dir: IntNotEqualDirective):
|
413
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
414
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
415
|
+
self.push(self.pop() != self.pop())
|
416
|
+
|
417
|
+
def handle_ult(self, dir: UnsignedLessThanDirective):
|
418
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
419
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
420
|
+
rhs = self.pop(signed=False)
|
421
|
+
lhs = self.pop(signed=False)
|
422
|
+
self.push(lhs < rhs)
|
423
|
+
|
424
|
+
def handle_ule(self, dir: UnsignedLessThanOrEqualDirective):
|
425
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
426
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
427
|
+
rhs = self.pop(signed=False)
|
428
|
+
lhs = self.pop(signed=False)
|
429
|
+
self.push(lhs <= rhs)
|
430
|
+
|
431
|
+
def handle_ugt(self, dir: UnsignedGreaterThanDirective):
|
432
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
433
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
434
|
+
rhs = self.pop(signed=False)
|
435
|
+
lhs = self.pop(signed=False)
|
436
|
+
self.push(lhs > rhs)
|
437
|
+
|
438
|
+
def handle_uge(self, dir: UnsignedGreaterThanOrEqualDirective):
|
439
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
440
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
441
|
+
rhs = self.pop(signed=False)
|
442
|
+
lhs = self.pop(signed=False)
|
443
|
+
self.push(lhs >= rhs)
|
444
|
+
|
445
|
+
def handle_slt(self, dir: SignedLessThanDirective):
|
446
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
447
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
448
|
+
rhs = self.pop()
|
449
|
+
lhs = self.pop()
|
450
|
+
self.push(lhs < rhs)
|
451
|
+
|
452
|
+
def handle_sle(self, dir: SignedLessThanOrEqualDirective):
|
453
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
454
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
455
|
+
rhs = self.pop()
|
456
|
+
lhs = self.pop()
|
457
|
+
self.push(lhs <= rhs)
|
458
|
+
|
459
|
+
def handle_sgt(self, dir: SignedGreaterThanDirective):
|
460
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
461
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
462
|
+
rhs = self.pop()
|
463
|
+
lhs = self.pop()
|
464
|
+
self.push(lhs > rhs)
|
465
|
+
|
466
|
+
def handle_sge(self, dir: SignedGreaterThanOrEqualDirective):
|
467
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
468
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
469
|
+
rhs = self.pop()
|
470
|
+
lhs = self.pop()
|
471
|
+
self.push(lhs >= rhs)
|
472
|
+
|
473
|
+
def handle_feq(self, dir: FloatEqualDirective):
|
474
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
475
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
476
|
+
rhs = self.pop(type=float)
|
477
|
+
lhs = self.pop(type=float)
|
478
|
+
print(rhs, lhs, rhs == lhs)
|
479
|
+
self.push(lhs == rhs)
|
480
|
+
|
481
|
+
def handle_fne(self, dir: FloatNotEqualDirective):
|
482
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
483
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
484
|
+
self.push(self.pop(type=float) != self.pop(type=float))
|
485
|
+
|
486
|
+
def handle_flt(self, dir: FloatLessThanDirective):
|
487
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
488
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
489
|
+
rhs = self.pop(type=float)
|
490
|
+
lhs = self.pop(type=float)
|
491
|
+
self.push(lhs < rhs)
|
492
|
+
|
493
|
+
def handle_fle(self, dir: FloatLessThanOrEqualDirective):
|
494
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
495
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
496
|
+
rhs = self.pop(type=float)
|
497
|
+
lhs = self.pop(type=float)
|
498
|
+
self.push(lhs <= rhs)
|
499
|
+
|
500
|
+
def handle_fgt(self, dir: FloatGreaterThanDirective):
|
501
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
502
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
503
|
+
rhs = self.pop(type=float)
|
504
|
+
lhs = self.pop(type=float)
|
505
|
+
self.push(lhs > rhs)
|
506
|
+
|
507
|
+
def handle_fge(self, dir: FloatGreaterThanOrEqualDirective):
|
508
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
509
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
510
|
+
rhs = self.pop(type=float)
|
511
|
+
lhs = self.pop(type=float)
|
512
|
+
self.push(lhs >= rhs)
|
513
|
+
|
514
|
+
def handle_not(self, dir: NotDirective):
|
515
|
+
if len(self.stack) < 1:
|
516
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
517
|
+
val = self.pop(type=bool, size=1)
|
518
|
+
if val:
|
519
|
+
self.push(False)
|
520
|
+
else:
|
521
|
+
self.push(True)
|
522
|
+
|
523
|
+
def handle_fpext(self, dir: FloatExtendDirective):
|
524
|
+
if len(self.stack) < 4:
|
525
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
526
|
+
val_bytes = self.stack[-4:]
|
527
|
+
self.stack = self.stack[:-4]
|
528
|
+
val_as_float = struct.unpack(">f", val_bytes)[0]
|
529
|
+
|
530
|
+
self.push(val_as_float)
|
531
|
+
|
532
|
+
def handle_siext_8_64(self, dir: IntegerSignedExtend8To64Directive):
|
533
|
+
if len(self.stack) < 1:
|
534
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
535
|
+
if len(self.stack) + 7 > self.max_stack_size:
|
536
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
537
|
+
|
538
|
+
# pop val off stack
|
539
|
+
val = self.pop(type=int, signed=True, size=1)
|
540
|
+
|
541
|
+
self.push(val, signed=True, size=8)
|
542
|
+
|
543
|
+
def handle_siext_16_64(self, dir: IntegerSignedExtend16To64Directive):
|
544
|
+
if len(self.stack) < 2:
|
545
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
546
|
+
if len(self.stack) + 6 > self.max_stack_size:
|
547
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
548
|
+
|
549
|
+
# pop val off stack
|
550
|
+
val = self.pop(type=int, signed=True, size=2)
|
551
|
+
|
552
|
+
self.push(val, signed=True, size=8)
|
553
|
+
|
554
|
+
def handle_siext_32_64(self, dir: IntegerSignedExtend32To64Directive):
|
555
|
+
if len(self.stack) < 4:
|
556
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
557
|
+
if len(self.stack) + 4 > self.max_stack_size:
|
558
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
559
|
+
|
560
|
+
# pop val off stack
|
561
|
+
val = self.pop(type=int, signed=True, size=4)
|
562
|
+
|
563
|
+
self.push(val, signed=True, size=8)
|
564
|
+
|
565
|
+
def handle_ziext_8_64(self, dir: IntegerZeroExtend8To64Directive):
|
566
|
+
if len(self.stack) < 1:
|
567
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
568
|
+
if len(self.stack) + 7 > self.max_stack_size:
|
569
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
570
|
+
|
571
|
+
# pop val off stack
|
572
|
+
val = self.pop(type=int, signed=False, size=1)
|
573
|
+
|
574
|
+
self.push(val, signed=False, size=8)
|
575
|
+
|
576
|
+
def handle_ziext_16_64(self, dir: IntegerZeroExtend16To64Directive):
|
577
|
+
if len(self.stack) < 2:
|
578
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
579
|
+
if len(self.stack) + 6 > self.max_stack_size:
|
580
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
581
|
+
|
582
|
+
# pop val off stack
|
583
|
+
val = self.pop(type=int, signed=False, size=2)
|
584
|
+
|
585
|
+
self.push(val, signed=False, size=8)
|
586
|
+
|
587
|
+
def handle_ziext_32_64(self, dir: IntegerZeroExtend32To64Directive):
|
588
|
+
if len(self.stack) < 4:
|
589
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
590
|
+
if len(self.stack) + 4 > self.max_stack_size:
|
591
|
+
return DirectiveErrorCode.STACK_OVERFLOW
|
592
|
+
|
593
|
+
# pop val off stack
|
594
|
+
val = self.pop(type=int, signed=False, size=4)
|
595
|
+
|
596
|
+
self.push(val, signed=False, size=8)
|
597
|
+
|
598
|
+
def handle_fptrunc(self, dir: FloatTruncateDirective):
|
599
|
+
if len(self.stack) < WORD_SIZE:
|
600
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
601
|
+
val_64 = self.pop(type=float)
|
602
|
+
val_32_bytes = struct.pack(">f", val_64)
|
603
|
+
self.push(val_32_bytes)
|
604
|
+
|
605
|
+
def handle_itrunc_64_8(self, dir: IntegerTruncate64To8Directive):
|
606
|
+
if len(self.stack) < 8:
|
607
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
608
|
+
|
609
|
+
val = self.pop(type=bytes, size=8)
|
610
|
+
val = val[-1 :]
|
611
|
+
self.push(val)
|
612
|
+
|
613
|
+
def handle_itrunc_64_16(self, dir: IntegerTruncate64To16Directive):
|
614
|
+
if len(self.stack) < 8:
|
615
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
616
|
+
|
617
|
+
val = self.pop(type=bytes, size=8)
|
618
|
+
val = val[-2 :]
|
619
|
+
self.push(val)
|
620
|
+
|
621
|
+
def handle_itrunc_64_32(self, dir: IntegerTruncate64To32Directive):
|
622
|
+
if len(self.stack) < 8:
|
623
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
624
|
+
|
625
|
+
val = self.pop(type=bytes, size=8)
|
626
|
+
val = val[-4 :]
|
627
|
+
self.push(val)
|
628
|
+
|
629
|
+
def handle_fptosi(self, dir: FloatToSignedIntDirective):
|
630
|
+
if len(self.stack) < WORD_SIZE:
|
631
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
632
|
+
val = self.pop(type=float)
|
633
|
+
self.push(val)
|
634
|
+
|
635
|
+
def handle_fptoui(self, dir: FloatToUnsignedIntDirective):
|
636
|
+
if len(self.stack) < WORD_SIZE:
|
637
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
638
|
+
val = self.pop(type=float)
|
639
|
+
self.push(val)
|
640
|
+
|
641
|
+
def handle_sitofp(self, dir: SignedIntToFloatDirective):
|
642
|
+
if len(self.stack) < WORD_SIZE:
|
643
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
644
|
+
val = self.pop()
|
645
|
+
self.push(float(val))
|
646
|
+
|
647
|
+
def handle_uitofp(self, dir: UnsignedIntToFloatDirective):
|
648
|
+
if len(self.stack) < WORD_SIZE:
|
649
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
650
|
+
val = self.pop(signed=False)
|
651
|
+
self.push(float(val))
|
652
|
+
|
653
|
+
def handle_iadd(self, dir: IntAddDirective):
|
654
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
655
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
656
|
+
rhs = self.pop()
|
657
|
+
lhs = self.pop()
|
658
|
+
self.push(overflow_check(lhs + rhs))
|
659
|
+
|
660
|
+
def handle_isub(self, dir: IntSubtractDirective):
|
661
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
662
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
663
|
+
rhs = self.pop()
|
664
|
+
lhs = self.pop()
|
665
|
+
self.push(overflow_check(lhs - rhs))
|
666
|
+
|
667
|
+
def handle_imul(self, dir: IntMultiplyDirective):
|
668
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
669
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
670
|
+
rhs = self.pop()
|
671
|
+
lhs = self.pop()
|
672
|
+
self.push(overflow_check(lhs * rhs))
|
673
|
+
|
674
|
+
def handle_udiv(self, dir: UnsignedIntDivideDirective):
|
675
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
676
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
677
|
+
rhs = self.pop(signed=False)
|
678
|
+
lhs = self.pop(signed=False)
|
679
|
+
|
680
|
+
# credit to gemini
|
681
|
+
if rhs == 0:
|
682
|
+
# C++ behavior for division by zero is undefined.
|
683
|
+
return DirectiveErrorCode.DIVIDE_BY_ZERO
|
684
|
+
|
685
|
+
# Perform division, truncating towards zero
|
686
|
+
# This is different from Python's // which floors.
|
687
|
+
python_quotient = int(lhs / rhs)
|
688
|
+
|
689
|
+
# For division, overflow detection isn't typically done with the mask on the result
|
690
|
+
# because the quotient itself is within range
|
691
|
+
self.push(python_quotient)
|
692
|
+
|
693
|
+
def handle_sdiv(self, dir: SignedIntDivideDirective):
|
694
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
695
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
696
|
+
rhs = self.pop(signed=True)
|
697
|
+
lhs = self.pop(signed=True)
|
698
|
+
|
699
|
+
# credit to gemini
|
700
|
+
if rhs == 0:
|
701
|
+
# C++ behavior for division by zero is undefined.
|
702
|
+
return DirectiveErrorCode.DIVIDE_BY_ZERO
|
703
|
+
|
704
|
+
# Special overflow case: MIN_INT64 / -1
|
705
|
+
# This results in MAX_INT64 + 1, which overflows to MIN_INT64 in C++.
|
706
|
+
if lhs == MIN_INT64 and rhs == -1:
|
707
|
+
self.push(MIN_INT64) # C++ specific overflow behavior
|
708
|
+
return
|
709
|
+
|
710
|
+
python_quotient = int(lhs / rhs)
|
711
|
+
|
712
|
+
self.push(python_quotient)
|
713
|
+
|
714
|
+
def handle_fadd(self, dir: FloatAddDirective):
|
715
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
716
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
717
|
+
rhs = self.pop(type=float)
|
718
|
+
lhs = self.pop(type=float)
|
719
|
+
self.push(lhs + rhs)
|
720
|
+
|
721
|
+
def handle_fsub(self, dir: FloatSubtractDirective):
|
722
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
723
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
724
|
+
rhs = self.pop(type=float)
|
725
|
+
lhs = self.pop(type=float)
|
726
|
+
self.push(lhs - rhs)
|
727
|
+
|
728
|
+
def handle_fmul(self, dir: FloatMultiplyDirective):
|
729
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
730
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
731
|
+
rhs = self.pop(type=float)
|
732
|
+
lhs = self.pop(type=float)
|
733
|
+
self.push(lhs * rhs)
|
734
|
+
|
735
|
+
def handle_fdiv(self, dir: FloatDivideDirective):
|
736
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
737
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
738
|
+
rhs = self.pop(type=float)
|
739
|
+
lhs = self.pop(type=float)
|
740
|
+
self.push(lhs / rhs)
|
741
|
+
|
742
|
+
def handle_smod(self, dir: SignedModuloDirective):
|
743
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
744
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
745
|
+
rhs = self.pop(signed=True)
|
746
|
+
lhs = self.pop(signed=True)
|
747
|
+
self.push(lhs % rhs, signed=True)
|
748
|
+
|
749
|
+
def handle_umod(self, dir: UnsignedModuloDirective):
|
750
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
751
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
752
|
+
rhs = self.pop(signed=False)
|
753
|
+
lhs = self.pop(signed=False)
|
754
|
+
self.push(lhs % rhs, signed=False)
|
755
|
+
|
756
|
+
def handle_fmod(self, dir: FloatModuloDirective):
|
757
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
758
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
759
|
+
rhs = self.pop(type=float)
|
760
|
+
lhs = self.pop(type=float)
|
761
|
+
self.push(lhs % rhs)
|
762
|
+
|
763
|
+
def handle_fpow(self, dir: FloatExponentDirective):
|
764
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
765
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
766
|
+
rhs = self.pop(type=float)
|
767
|
+
lhs = self.pop(type=float)
|
768
|
+
self.push(lhs**rhs)
|
769
|
+
|
770
|
+
def handle_log(self, dir: FloatLogDirective):
|
771
|
+
if len(self.stack) < WORD_SIZE:
|
772
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
773
|
+
operand = self.pop(type=float)
|
774
|
+
self.push(math.log(operand))
|
775
|
+
|
776
|
+
def handle_float_floor_div(self, dir: FloatFloorDivideDirective):
|
777
|
+
if len(self.stack) < 2 * WORD_SIZE:
|
778
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
779
|
+
rhs = self.pop(type=float)
|
780
|
+
lhs = self.pop(type=float)
|
781
|
+
self.push(lhs // rhs)
|
782
|
+
|
783
|
+
def handle_exit(self, dir: ExitDirective):
|
784
|
+
if len(self.stack) < 1:
|
785
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
786
|
+
success = self.pop(type=bool, size=1)
|
787
|
+
if success:
|
788
|
+
self.next_dir_idx = len(self.dirs)
|
789
|
+
else:
|
790
|
+
return DirectiveErrorCode.DELIBERATE_FAILURE
|
791
|
+
|
792
|
+
def handle_memcmp(self, dir: MemCompareDirective):
|
793
|
+
if len(self.stack) < dir.size * 2:
|
794
|
+
return DirectiveErrorCode.STACK_UNDERFLOW
|
795
|
+
|
796
|
+
rhs = self.pop(type=bytes, size=dir.size)
|
797
|
+
lhs = self.pop(type=bytes, size=dir.size)
|
798
|
+
print(rhs, lhs)
|
799
|
+
self.push(rhs == lhs)
|