-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbonetools.py
103 lines (92 loc) · 3.94 KB
/
bonetools.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# 20191205
# original https://github.com/tpwrules/ice_panel
# converted to tinyfgpa_bx by Simon Kirkby
# some nice tools for coding boneless asm
from boneless.gateware import ALSRU_4LUT, CoreFSM
from boneless.arch.opcode import Instr
from boneless.arch.opcode import *
# help assign registers to names
class RegisterManager:
# we could instantiate a new Reg each time, but looking up here is faster
# and also ensures each register is the same object, if that's ever useful.
BREGS = [R0, R1, R2, R3, R4, R5, R6, R7]
def __init__(self, reglist=None):
self._name2reg = {}
self._reg2name = {}
if reglist is not None:
self += reglist
# add some registers to be managed.
# other is a string representing the new register names. each assignment
# is the form of Rn:name such that after this operation, self.name is Rn.
# assignments are separated by whitespace.
def __iadd__(self, other):
if not isinstance(other, str):
raise TypeError("expected str, not '{}'".format(type(other)))
add = {} # add all at once so we don't half-assign on exception
for assignment in other.split():
reg, name = assignment.split(":")
if len(reg) != 2 or reg[0] != "R" or reg[1] not in "0123456789":
raise ValueError("register '{}' is not 'Rn' form".format(reg))
reg = int(reg[1])
if reg > 7:
raise ValueError("register R{} does not exist".format(reg))
if not name.isidentifier():
raise ValueError(
"name '{}' is not a valid " "Python identifier".format(name)
)
if reg in self._reg2name or reg in add:
try:
name = self._reg2name[reg]
except KeyError:
name = add[reg]
raise ValueError(
"register R{} already assigned " "to name '{}'".format(reg, name)
)
if name in self._name2reg:
raise ValueError(
"name '{}' already assigned "
"to register R{}".format(name, self._name2reg[name])
)
add[reg] = name
for reg, name in add.items():
self._name2reg[name] = reg
self._reg2name[reg] = name
return self
# remove some registers to be managed.
# other is a string representing register names to remove. removals are
# separated by whitespace. if the first character is !, all registers
# except those given are removed
def __isub__(self, other):
if not isinstance(other, str):
raise TypeError("expected str, not '{}'".format(type(other)))
if other.startswith("!"):
invert = True
other = other[1:]
else:
invert = False
rem = [] # remove all at once so we don't half-remove on exception
if not invert:
for name in other.split():
if name not in self._name2reg:
raise KeyError("name '{}' not currently assigned".format(name))
rem.append(name)
else:
# assume we're removing everything
rem = set(self._name2reg.keys())
# then remove things from that list that we want to keep
for name in other.split():
if name not in self._name2reg:
raise KeyError("name '{}' not currently assigned".format(name))
del rem[name]
rem = list(rem)
for name in rem:
reg = self._name2reg[name]
del self._name2reg[name]
del self._reg2name[reg]
return self
# return a register assignment if it's available
def __getattr__(self, name):
ri = self._name2reg.get(name)
if ri is None:
raise KeyError("name '{}' not currently assigned".format(name))
return RegisterManager.BREGS[ri]