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
104
105
106
107
108
109
110
111
|
#!/usr/bin/env python3
""" pack.py
Packs bitfields tagged with their size into untagged bytes.
>>> from io import StringIO
>>> # doctest: +REPORT_NDIFF
... print(subv.join_all(pack(StringIO('''
... == code 0x80000000
... main:
... 37/7 05/5 10010/20
... 13/7 06/5 00/3 00/5 48/12
... 23/7 00/5 02/3 05/5 06/5 00/7
... 13/7 06/5 00/3 00/5 65/12
... 23/7 00/5 02/3 05/5 06/5 00/7
... 13/7 06/5 00/3 00/5 6c/12
... 23/7 00/5 02/3 05/5 06/5 00/7
... 13/7 06/5 00/3 00/5 6c/12
... 23/7 00/5 02/3 05/5 06/5 00/7
... 13/7 06/5 00/3 00/5 6f/12
... 23/7 00/5 02/3 05/5 06/5 00/7
... 13/7 06/5 00/3 00/5 0a/12
... 23/7 00/5 02/3 05/5 06/5 00/7
... 6f/7 00/5 ff/8 1/1 3e6/10 1/1
... '''[1:-1]))))
== code 0x80000000
main:
b7 02 01 10
13 03 80 04
23 a0 62 00
13 03 50 06
23 a0 62 00
13 03 c0 06
23 a0 62 00
13 03 c0 06
23 a0 62 00
13 03 f0 06
23 a0 62 00
13 03 a0 00
23 a0 62 00
6f f0 df fc
"""
import subv
import bits
def byteify(word):
"""split longer bitfield into bytes.
>>> byteify(bits.Bitfield(0x12345678, 32))
[(120,), (86,), (52,), (18,)]
>>> byteify(bits.Bitfield(0x4801813, 32))
[(19,), (24,), (128,), (4,)]
>>> byteify(bits.Bitfield(0x13, 9)),
Traceback (most recent call last):
...
AssertionError: not byte aligned: 013/9
"""
assert word.size % 8 == 0, "not byte aligned: {}".format(word)
out = []
for i in range(0, word.size, 8):
byte = word[i + 7 : i]
out.append((byte.val,))
return out
@subv.with_parsed_lines
def pack(iter):
out = []
buf = bits.empty
def flush_bytes():
line = " ".join("{:02x}".format(b.val) for b in out)
out.clear()
return line
last_segment = None
for segment, line in iter:
if last_segment != segment:
assert buf.size == 0, "segment '{}' end isn't byte-aligned".format(segment)
if out:
yield subv.format(flush_bytes())
if line["type"] == "instr":
for part in line["instr"]:
buf = bits.from_part(part) & buf
else:
yield line["raw"]
while buf.size >= 8:
byte = buf[7:0]
buf = buf.slice_allowempty(slice(buf.size - 1, 8))
out.append(byte)
if len(out) == 4:
yield flush_bytes()
last_segment = segment
assert buf.size == 0, "segment '{}' end isn't byte-aligned".format(segment)
if len(out) > 0:
yield flush_bytes()
if __name__ == "__main__":
import sys
for line in pack(sys.stdin):
print(line)
|