-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathparsegen.py
170 lines (146 loc) · 5.03 KB
/
parsegen.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
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import argparse, re
def mnem2enum(m):
return 'INS_' + m
def outMnem(fd, mnem, flaglist):
cflags = '|'.join(flaglist)
if not cflags:
cflags = '0'
name = '"%s",' % mnem
fd.write('{ %-10s %-32s },\n' % (name, cflags))
def outMnemEnum(fd, mnem):
fd.write(' %s,\n' % mnem2enum(mnem))
def main():
parser = argparse.ArgumentParser(description='Instruction set parsing table generator.')
parser.add_argument('infile', type=argparse.FileType('r'))
args = parser.parse_args()
mnems = dict()
parseinfo = ([],[],[])
for line in args.infile.readlines():
# Trim comment
pos = line.find('#')
if pos >= 0:
line = line[:pos]
# Remove whitespaces
line = line.translate(None, ' \r\n')
values = line.split(',')
if len(values) < 2:
continue
# Encoding: Translate bit description to code + mask
bits = values.pop()
bits = [ (b, '1') if b == '1' or b == '0' else ('0','0') for b in bits ]
bits = zip(*bits)
code = int(''.join(bits[0]), 2)
mask = int(''.join(bits[1]), 2)
# Mnemonics
mnem = values.pop(0)
# Ops
ops = [None] * len(values)
cflags = []
opflags = []
opindex = 0
opcounter = 0
for opcode in values:
displ = False
changed = False
mem = False
used = False
cf_call = False
cf_jump = False
posflag = 0
#Extract flags
for c in opcode:
if c.isalnum():
break
if c == '!':
cflags.append('CF_STOP')
elif c == '%':
cf_jump = True
elif c == '^':
cf_call = True
elif c == '>':
changed = True
elif c == '+':
displ = True
elif c == '*':
mem = True
#Extract position, if any
if len(opcode) > 2 and opcode[-2] == '@':
posflag = int(opcode[-1])
opcode = opcode[:-2]
opcode = opcode.lstrip('!>^*+%')
if opcode and not displ:
used = True
if opcode.startswith('BRANCH'):
cf_jump = True
if opcode.startswith('CALL'):
cf_call = True
if posflag:
opindex = posflag - 1
else:
opindex = opcounter
opval = []
if opcode:
opval.append('OPG_' + opcode)
if displ:
opval.append('OPGF_RELATIVE')
if mem:
if mnem.endswith('W'):
opval.append('OPGF_MEM16')
else:
opval.append('OPGF_MEM8')
if posflag:
opval.append('OPGF_SHOWAT_%d' % opcounter)
if cf_call:
cflags.append('CF_CALL')
if cf_jump:
cflags.append('CF_JUMP')
ops[opindex] = ' | '.join(opval)
opflags.append((used, changed))
opcounter += 1
# Update display order dependent CF flags
opindex = 0
for used, changed in opflags:
if used:
opindex += 1
cflags.append('CF_USE%d' % opindex)
if changed:
cflags.append('CF_CHG%d' % opindex)
# Split codes by extension
extension = code >> 8
if extension not in (0,2,3):
print 'ERROR: invalid code detected for %s: %s' % (mnem, bin(code))
continue
if extension > 0:
extension -= 1
code &= 0xFF
mask &= 0xFF
cflags = tuple(cflags)
# Add a suffix for different forms of the same mnemonic
original_mnem = mnem
renamesuffix = 0
while (mnem in mnems) and (mnems[mnem] != cflags):
renamesuffix += 1
mnem = '%s_%d' % (original_mnem, renamesuffix)
values = (hex(code), hex(mask), mnem2enum(mnem)) + tuple(ops)
parseinfo[extension].append(values)
mnems[mnem] = cflags
# Output parsetables
for extension, pinfo in enumerate(parseinfo):
with open('parsetable%d.gen.c' % extension, 'w') as fd:
for values in pinfo:
fd.write('{ %s },\n' % ', '.join(values))
mnems = mnems.items()
mnems.sort()
# Output instruc_t table
with open('instructions.gen.c', 'w') as fd:
outMnem(fd, '', [])
for mnem in mnems:
outMnem(fd, *mnem)
# Output instructions enum
with open('instructions.gen.h', 'w') as fd:
outMnemEnum(fd, 'NULL = 0')
for mnem in mnems:
outMnemEnum(fd, mnem[0])
outMnemEnum(fd, 'LAST')
if __name__ == '__main__':
main()