1#!/usr/bin/python
2# convert LLVM GenRegisterInfo.inc for Capstone disassembler.
3# by Nguyen Anh Quynh, 2019
4
5import sys
6
7if len(sys.argv) == 1:
8    print("Syntax: %s <GenRegisterInfo.inc> <architecture>" %sys.argv[0])
9    sys.exit(1)
10
11f = open(sys.argv[1])
12lines = f.readlines()
13f.close()
14
15arch = sys.argv[2]
16
17print("""
18/* Capstone Disassembly Engine, http://www.capstone-engine.org */
19/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
20
21/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\\
22|*                                                                            *|
23|* Target Register Enum Values                                                *|
24|*                                                                            *|
25|* Automatically generated file, do not edit!                                 *|
26|*                                                                            *|
27\*===----------------------------------------------------------------------===*/
28
29#ifdef GET_REGINFO_ENUM
30#undef GET_REGINFO_ENUM
31""")
32
33enum_count = 0
34
35# 1st enum is register enum
36for line in lines:
37    line = line.rstrip()
38
39    if len(line.strip()) == 0:
40        continue
41
42    if line.strip() == 'enum {':
43        enum_count += 1
44        print(line)
45        continue
46
47    if enum_count == 1:
48        if line.strip() == '};':
49            print(line)
50            # done with first enum
51            break
52        else:
53            # enum items
54            print("  %s_%s" %(arch, line.strip()))
55
56# 2nd enum is register class
57enum_count = 0
58print("\n// Register classes")
59for line in lines:
60    line = line.rstrip()
61
62    if len(line.strip()) == 0:
63        continue
64
65    if line.strip() == 'enum {':
66        enum_count += 1
67        if enum_count == 2:
68            print(line)
69        continue
70
71    if enum_count == 2:
72        if line.strip() == '};':
73            # done with 2nd enum
74            print(line.strip())
75            break
76        else:
77            # enum items
78            print("  %s_%s" %(arch, line.strip()))
79
80if arch.upper() == 'ARM':
81    # 3rd enum is Subregister indices
82    enum_count = 0
83    print("\n// Subregister indices")
84    for line in lines:
85        line = line.rstrip()
86
87        if len(line.strip()) == 0:
88            continue
89
90        if line.strip() == 'enum {':
91            enum_count += 1
92            if enum_count == 3:
93                print(line)
94            continue
95
96        if enum_count == 3:
97            if line.strip() == '};':
98                # done with 2nd enum
99                print(line.strip())
100                break
101            else:
102                # enum items
103                print("  %s_%s" %(arch, line.strip()))
104
105if arch.upper() == 'AARCH64':
106    # 3rd enum is Register alternate name indices
107    enum_count = 0
108    print("\n// Register alternate name indices")
109    for line in lines:
110        line = line.rstrip()
111
112        if len(line.strip()) == 0:
113            continue
114
115        if line.strip() == 'enum {':
116            enum_count += 1
117            if enum_count == 3:
118                print(line)
119            continue
120
121        if enum_count == 3:
122            if line.strip() == '};':
123                # done with 2nd enum
124                print(line.strip())
125                break
126            else:
127                # enum items
128                print("  %s_%s" %(arch, line.strip()))
129
130    # 4th enum is Subregister indices
131    enum_count = 0
132    print("\n// Subregister indices")
133    for line in lines:
134        line = line.rstrip()
135
136        if len(line.strip()) == 0:
137            continue
138
139        if line.strip() == 'enum {':
140            enum_count += 1
141            if enum_count == 4:
142                print(line)
143            continue
144
145        if enum_count == 4:
146            if line.strip() == '};':
147                # done with 2nd enum
148                print(line.strip())
149                break
150            else:
151                # enum items
152                print("  %s_%s" %(arch, line.strip()))
153
154# end of enum
155print("")
156print("#endif // GET_REGINFO_ENUM")
157
158print("""
159#ifdef GET_REGINFO_MC_DESC
160#undef GET_REGINFO_MC_DESC
161
162""")
163
164# extract RegDiffLists
165finding_struct = True
166for line in lines:
167    line = line.rstrip()
168
169    if len(line.strip()) == 0:
170        continue
171
172    if arch + 'RegDiffLists' in line:
173        finding_struct = False
174        print("static const MCPhysReg " + arch + "RegDiffLists[] = {")
175        continue
176
177    if finding_struct:
178        continue
179    else:
180        print(line)
181        if line == '};':
182            # done with this struct
183            print("")
184            break
185
186# extract SubRegIdxLists
187finding_struct = True
188for line in lines:
189    line = line.rstrip()
190
191    if len(line.strip()) == 0:
192        continue
193
194    if arch + 'SubRegIdxLists' in line:
195        finding_struct = False
196        print("static const uint16_t " + arch + "SubRegIdxLists[] = {")
197        continue
198
199    if finding_struct:
200        continue
201    else:
202        print(line)
203        if line == '};':
204            # done with this struct
205            print("")
206            break
207
208# extract RegDesc
209finding_struct = True
210for line in lines:
211    line = line.rstrip()
212
213    if len(line.strip()) == 0:
214        continue
215
216    if arch + 'RegDesc' in line:
217        finding_struct = False
218        print("static const MCRegisterDesc " + arch + "RegDesc[] = {")
219        continue
220
221    if finding_struct:
222        continue
223    else:
224        print(line)
225        if line == '};':
226            # done with this struct
227            print("")
228            break
229
230# extract register classes
231finding_struct = True
232for line in lines:
233    line = line.rstrip()
234
235    if len(line.strip()) == 0:
236        continue
237
238    if 'Register classes' in line and 'namespace' in line:
239        finding_struct = False
240        continue
241
242    if finding_struct:
243        continue
244    else:
245        if 'const' in line:
246            line2 = line.replace('const', 'static const')
247            print(line2)
248        elif '::' in line:
249            line2 = line.replace('::', '_')
250            print(line2)
251        elif 'end anonymous namespace' in line:
252            # done with this struct
253            break
254        else:
255            print(line)
256
257print("\n")
258
259# extract MCRegisterClasses
260finding_struct = True
261for line in lines:
262    line = line.rstrip()
263
264    if len(line.strip()) == 0:
265        continue
266
267    if 'MCRegisterClass ' + arch + 'MCRegisterClasses[] = {' in line:
268        finding_struct = False
269        print("static const MCRegisterClass " + arch + "MCRegisterClasses[] = {")
270        continue
271
272    if finding_struct:
273        continue
274    else:
275        if line == '};':
276            # done with this struct
277            print('};\n')
278            break
279        elif '::' in line:
280            line = line.replace('::', '_')
281
282        # { GR8, GR8Bits, 130, 20, sizeof(GR8Bits), X86_GR8RegClassID, 1, 1, 1, 1 },
283        tmp = line.split(',')
284        print("  %s, %s, %s }," %(tmp[0].strip(), tmp[1].strip(), tmp[4].strip()))
285
286print("#endif // GET_REGINFO_MC_DESC")
287