Project Ne10
An Open Optimized Software Library Project for the ARM Architecture
Loading...
Searching...
No Matches
gas2ios_convert.py
1#!/usr/bin/python
2'''
3 Copyright 2013-15 ARM Limited and Contributors.
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of ARM Limited nor the
14 names of its contributors may be used to endorse or promote products
15 derived from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL ARM LIMITED AND CONTRIBUTORS BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.'''
27
28'''convert GAS arm assembly to Clang's integrated-as'''
29import re,sys,os
30
31''' parse .qn .dn .req directive for arm assembly
32 input is string list
33'''
34def parse_alias(inlines):
35 #the value name doesn't include .F32 suffix, but include [0], such as d0[0]
36 alias_exp = re.compile(r" *"
37 r"(?P<alias>[_a-zA-Z0-9]+)"
38 " +\.(req|qn|dn) +"
39 r"(?P<value>[a-zA-Z0-9\[\]]+)"
40 )
41 global_exp = re.compile(r"\.global")
42 #store aliases in different function in different dictionary
43 #use .global to label different function
44 alias_dics = []
45 alias_dics.append({})
46 func_count = 0
47 for line in inlines:
48 if global_exp.search(line):
49 alias_dics.append({})
50 func_count += 1
51 result = alias_exp.search(line)
52 if result != None:
53 alias = result.group('alias')
54 value = result.group('value')
55 alias_dics[func_count][alias] = value
56 #print alias_dics
57
58 #replace alias
59 func_count = 0
60 line_result1 = []
61 for line in inlines:
62 if global_exp.search(line):
63 func_count += 1
64 for alias in alias_dics[func_count]:
65 alias_str = "\\b"+alias+"\\b"
66 alias_exp = re.compile(alias_str)
67 line = alias_exp.sub(alias_dics[func_count][alias], line)
68 line_result1.append(line)
69
70 #remove .qn .dn .req line
71 line_result2 = []
72 alias_exp = re.compile(r"\.(qn|dn|req|unreq)")
73 for line in line_result1:
74 if not alias_exp.search(line):
75 line_result2.append(line)
76
77 return line_result2
78
79''' parse .qn .dn .req directive for arm assembly
80 input is string list.
81 this is for fft module's new format: in the new format,
82 all aliases are defined at the begin of files and all functions
83 share one set of defines.
84'''
85def parse_alias_fft(inlines):
86 #the value name doesn't include .F32 suffix, but include [0], such as d0[0]
87 alias_exp = re.compile(r" *"
88 r"(?P<alias>[_a-zA-Z0-9]+)"
89 " +\.(req|qn|dn) +"
90 r"(?P<value>[a-zA-Z0-9\[\]]+)"
91 )
92 aliases = {}
93 for line in inlines:
94 result = alias_exp.search(line)
95 if result != None:
96 alias = result.group('alias')
97 value = result.group('value')
98 aliases[alias] = value
99 #print aliases
100
101 #replace alias
102 line_result1 = []
103 for line in inlines:
104 for alias in aliases:
105 alias_str = "\\b"+alias+"\\b"
106 alias_exp = re.compile(alias_str)
107 line = alias_exp.sub(aliases[alias], line)
108 line_result1.append(line)
109
110 #remove .qn .dn .req line
111 line_result2 = []
112 alias_exp = re.compile(r"\.(qn|dn|req|unreq)")
113 for line in line_result1:
114 if not alias_exp.search(line):
115 line_result2.append(line)
116
117 return line_result2
118
119'''add .F32 to some instructions for Clang's as doesn't support register with
120 datatype, such as VADD Q0.F32, Q1.F32, Q2.F32'''
121def add_f32(inlines):
122 instructions = ['VADD', 'VSUB', 'VLD1', 'VLD2', 'VMUL', 'VMLA', 'VMLS',
123 'VZIP', 'VST1', 'VST2', 'VPADD', 'VEXT', 'VREV64',
124 'VDUP', 'VMOV']
125 line_result = []
126 for line in inlines:
127 for instruction in instructions:
128 instruction_exp = re.compile(instruction)
129 instruction_f32_exp = re.compile(instruction + "\\.[Ff]32")
130 #only add .F32 to instruction without .F32(or .f32)
131 if instruction_exp.search(line) and \
132 not instruction_f32_exp.search(line):
133 line = instruction_exp.sub(instruction + ".F32", line)
134 line_result.append(line)
135 return line_result
136
137'''remove .end instruction'''
138def remove_end(inlines):
139 end_exp = re.compile(r"\.end\b")
140 line_result = []
141 for line in inlines:
142 if not end_exp.search(line):
143 line_result.append(line)
144 return line_result
145
146'''expan ldr rx, =label for Clang, this method has *not* been used in current
147assembly convertion, Clang doesn't support this pseudo-instruction'''
148def expan_ldr1(inlines):
149 #search ldr rx, =label
150 labels = []
151 ldr_exp = re.compile(r"\s*LDR.*="
152 r"(?P<label>[_a-zA-Z0-9]+)")
153 for line in inlines:
154 result = ldr_exp.search(line)
155 if result != None:
156 label = result.group('label')
157 if label not in labels:
158 labels.append(label)
159 #print labels
160
161 if labels:
162 #change ldr rx, =label to ldr rx, Llabel
163 lines_result1 = []
164 for line in inlines:
165 result_line = line
166 for label in labels:
167 ldr_exp = re.compile("=" + label)
168 if ldr_exp.search(line):
169 result_line = ldr_exp.sub("L" + label, line)
170 break
171 lines_result1.append(result_line)
172
173 #append a .text section to file and also add local label
174 lines_result1.append(" .text\n")
175 lines_result1.append(" .align 2\n")
176 for label in labels:
177 lines_result1.append("L" + label + ":\n")
178 lines_result1.append(" .long " + label + "\n")
179
180 #remove .extern directive which is only used in GNU as
181 lines_result2 = []
182 for line in lines_result1:
183 del_line = False
184 for label in labels:
185 extern_exp = re.compile(r"\s*\.extern\s*" + label)
186 if extern_exp.search(line):
187 del_line = True
188 if not del_line:
189 lines_result2.append(line)
190 return lines_result2
191 return inlines
192
193'''expan ldr rx, =label for Clang, Clang doesn't support this
194pseudo-instruction'''
195def expan_ldr2(inlines):
196 #search "ldr rx, =label" line, save the label
197 labels = []
198 ldr_exp = re.compile(r"\s*(LDR|ldr)\s*(?P<reg>[a-zA-Z0-9]+),\s*="
199 r"(?P<label>[_a-zA-Z0-9]+)")
200 for line in inlines:
201 result = ldr_exp.search(line)
202 if result != None:
203 label = result.group('label')
204 if label not in labels:
205 labels.append(label)
206 #print labels
207
208 if labels:
209 #change ldr rx, =label to ldr rx, Llabel
210 lines_result1 = []
211 count = 0
212 for line in inlines:
213 result_line = line
214 for label in labels:
215 result = ldr_exp.search(line)
216 if result:
217 reg = result.group('reg')
218 result_line = " MOVW "\
219 + reg + ",:lower16:(L" + label +\
220 "$non_lazy_ptr - (LPC0_" + str(count) + " + 4))\n" +\
221 " MOVT " + reg +\
222 ",:upper16:(L" + label + "$non_lazy_ptr - (LPC0_" +\
223 str(count) + " + 4))\n" + "LPC0_" + str(count) + ":\n"\
224 + " ADD " + reg + \
225 ",PC\n" + " LDR " +\
226 reg + ",[" + reg + "]\n"
227 count += 1
228 break
229 lines_result1.append(result_line)
230
231 #append a .text section to file and also add local label
232 lines_result1.append(" .section __DATA,__nl_symbol_ptr,\
233 non_lazy_symbol_pointers\n")
234 lines_result1.append(" .align 2\n")
235 for label in labels:
236 lines_result1.append("L" + label + "$non_lazy_ptr:\n")
237 lines_result1.append(" .indirect_symbol " + label + "\n")
238 lines_result1.append(" .long 0\n")
239 lines_result1.append("\n .subsections_via_symbols\n")
240
241 #remove .extern directive which is only used in GNU as
242 lines_result2 = []
243 for line in lines_result1:
244 del_line = False
245 for label in labels:
246 extern_exp = re.compile(r"\s*\.extern\s*" + label)
247 if extern_exp.search(line):
248 del_line = True
249 if not del_line:
250 lines_result2.append(line)
251 return lines_result2
252 return inlines
253
254'''add prefix 'L' to local label '''
255def add_Llabel(inlines):
256 #get global label
257 glabels = []
258 for line in inlines:
259 glabel_exp = re.compile(r"\s*\.globa?l\s*"
260 r"(?P<glabel>\b[_a-zA-Z0-9]+\b)")
261 result = glabel_exp.search(line)
262 if result:
263 glabels.append(result.group('glabel'))
264 #print glabels
265
266 #get non-leading L local label
267 llabels = []
268 for line in inlines:
269 llabel_exp = re.compile(r"(?P<llabel>^[._a-zA-Z0-9]+):")
270 result = llabel_exp.search(line)
271 if result:
272 llabel = result.group('llabel')
273 leading_L_exp = re.compile(r"^L.*")
274 if llabel not in glabels and not leading_L_exp.search(llabel):
275 llabels.append(llabel)
276
277 #print llabels
278 #add leading L to local label
279 result_lines = []
280 for line in inlines:
281 result_line = line
282 for llabel in llabels:
283 new_llabel = llabel.replace('.L','')
284 #apply different change to label with .L or not
285 if new_llabel != llabel:
286 llabel_exp = re.compile(llabel.replace('.','\\.'))
287 else:
288 llabel_exp = re.compile("\\b" + llabel + "\\b")
289 #print "\\b" + re.escape(llabel) + "\\b"
290 if llabel_exp.search(line):
291 result_line = llabel_exp.sub("L" + new_llabel, line)
292 break
293 result_lines.append(result_line)
294
295 return result_lines
296
297def main ():
298 fft_file_names = ['NE10_fft_float32.neon.s',
299 'NE10_fft_int16.neon.s',
300 'NE10_fft_int32.neon.s']
301 if len(sys.argv) < 3:
302 print "Usage: convert.py <input file> <output file>"
303 return
304 else:
305 infilename = sys.argv[1]
306 outfilename = sys.argv[2]
307 infile = open(infilename, 'r')
308 lines = []
309 for line in infile.readlines():
310 lines.append(line)
311 infile.close()
312
313 #the fft file processing is hard coded.
314 if os.path.basename(infilename) in fft_file_names:
315 result = parse_alias_fft(lines)
316 else:
317 result = parse_alias(lines)
318 result = add_f32(result)
319 result = remove_end(result)
320 result = add_Llabel(result)
321 result = expan_ldr2(result)
322
323 outfile = open(outfilename, 'w')
324 for line in result:
325 outfile.write(line)
326 outfile.close()
327
328main()