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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
#!/usr/bin/env python
import re
import sys
import math
# word = int(sys.argv[1], 16)
def field_disp(lm):
if lm[0] == lm[1]:
return "%d" % lm[0]
else:
return "%d:%d" % (lm[0], lm[1])
def inv_sort_sizes(sz):
return sorted([(v, k) for k, v in sz.iteritems()])
class Desc(object):
SIZES = {
'B': 8,
'W': 16,
'D': 32,
'Q': 64,
}
INV_SIZES = inv_sort_sizes(SIZES)
def __init__(self, lines):
self.struct = []
self.cur = []
self.curname = None
self.curbase = None
self.cursz = None
self.up = None
self.base = 0 # base offset (in bits)
for lnum, line in enumerate(lines):
lnum += 1
line = line.strip()
if not line:
continue
if line.upper() in self.SIZES:
self.new_word(line.upper())
continue
parts = re.split(r"\s*:\s*", line)
if len(parts) == 1:
parts = parts * 2
if len(parts) > 2:
raise ValueError("bad line: %s" % line)
limits = [int(p) for p in parts]
if limits[0] < limits[1]:
raise ValueError("wrong order in line %d: %r" % (lnum, line))
if limits[1] < 0:
raise ValueError("bad bit num in line %d: %r" % (lnum, line))
if self.cursz is None:
for bn, size_qual in self.INV_SIZES:
if bn > limits[0]:
self.new_word(size_qual, "auto ")
break
else:
raise ValueError("out of range bitfield in line %d: %r" %
(lnum, line))
if limits[0] + 1 > self.up:
raise ValueError("out of range or not in decreasing order "
"at line %d: %r" % (lnum, line))
if limits[0] + 1 < self.up:
auto_ins = [self.up - 1, limits[0] + 1]
self.ins_bitfield(auto_ins, "auto ")
self.ins_bitfield(limits)
if limits[1] == 0:
self.close_cur()
self.close_cur()
def ins_bitfield(self, bf, why=""):
print "%sinserting bit field %s" % (why, field_disp(bf))
self.up = bf[1]
self.cur.append(bf)
def new_word(self, size_qual, why=""):
bit_num = self.SIZES[size_qual]
self.close_cur()
self.cursz = self.up = bit_num
self.curbase = self.base
self.curname = "%s@%d(%d)" % (size_qual, self.base / 8, self.base)
self.base += bit_num
print "%snew word %s" % (why, self.curname)
def close_cur(self):
if self.cursz is None:
return
if not self.cur:
self.ins_bitfield([self.cursz - 1, 0], "auto ")
elif self.cur[-1][1] > 0:
self.ins_bitfield([self.cur[-1][1] - 1, 0], "auto ")
print "closing %s" % self.curname
self.struct.append((self.curname, self.curbase, self.cur))
self.cur = []
self.curname = None
self.cursz = None
self.up = None
def parse_print(self, val):
for name, base, fields in self.struct:
wval = val >> base
print "%s:" % name
for hb, lb in fields:
bn = (hb - lb + 1)
fval = (wval >> lb) & ((1 << bn) - 1)
print " %s\t%sb\t%sh\t%d" % (
field_disp([hb, lb]),
to_bin(fval, bn),
to_hex(fval, bn),
fval)
def to_bin(v, bn):
pref = ""
if v & ((1 << bn) - 1) != v:
pref = "OVERFLOW:"
bn = int((math.ceil(math.log(v + 1, 2))))
return pref + ''.join([str((v >> i) & 1) for i in xrange(bn - 1, -1, -1)])
def to_hex(v, bn):
hn = (bn + 3) / 4
fmt = "%%0%dx" % hn
return fmt % v
desc = Desc(sys.stdin)
print
desc.parse_print(int(sys.argv[1], 16))
|