arm: Use the UAL syntax for instructions
[opus.git] / celt / arm / arm2gnu.pl
1 #!/usr/bin/perl
2 # Copyright (C) 2002-2013 Xiph.org Foundation
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
6 # are met:
7 #
8 # - Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 #
11 # - Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 # OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 my $bigend;  # little/big endian
28 my $nxstack;
29
30 $nxstack = 0;
31
32 eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}'
33     if $running_under_some_shell;
34
35 while ($ARGV[0] =~ /^-/) {
36     $_ = shift;
37   last if /^--/;
38     if (/^-n/) {
39     $nflag++;
40     next;
41     }
42     die "I don't recognize this switch: $_\\n";
43 }
44 $printit++ unless $nflag;
45
46 $\ = "\n";      # automatically add newline on print
47 $n=0;
48
49 $thumb = 0;     # ARM mode by default, not Thumb.
50 @proc_stack = ();
51
52 printf ("    .syntax unified\n");
53
54 LINE:
55 while (<>) {
56
57     # For ADRLs we need to add a new line after the substituted one.
58     $addPadding = 0;
59
60     # First, we do not dare to touch *anything* inside double quotes, do we?
61     # Second, if you want a dollar character in the string,
62     # insert two of them -- that's how ARM C and assembler treat strings.
63     s/^([A-Za-z_]\w*)[ \t]+DCB[ \t]*\"/$1:   .ascii \"/   && do { s/\$\$/\$/g; next };
64     s/\bDCB\b[ \t]*\"/.ascii \"/                          && do { s/\$\$/\$/g; next };
65     s/^(\S+)\s+RN\s+(\S+)/$1 .req r$2/                    && do { s/\$\$/\$/g; next };
66     # If there's nothing on a line but a comment, don't try to apply any further
67     #  substitutions (this is a cheap hack to avoid mucking up the license header)
68     s/^([ \t]*);/$1@/                                     && do { s/\$\$/\$/g; next };
69     # If substituted -- leave immediately !
70
71     s/@/,:/;
72     s/;/@/;
73     while ( /@.*'/ ) {
74       s/(@.*)'/$1/g;
75     }
76     s/\{FALSE\}/0/g;
77     s/\{TRUE\}/1/g;
78     s/\{(\w\w\w\w+)\}/$1/g;
79     s/\bINCLUDE[ \t]*([^ \t\n]+)/.include \"$1\"/;
80     s/\bGET[ \t]*([^ \t\n]+)/.include \"${ my $x=$1; $x =~ s|\.s|-gnu.S|; \$x }\"/;
81     s/\bIMPORT\b/.extern/;
82     s/\bEXPORT\b/.global/;
83     s/^(\s+)\[/$1IF/;
84     s/^(\s+)\|/$1ELSE/;
85     s/^(\s+)\]/$1ENDIF/;
86     s/IF *:DEF:/ .ifdef/;
87     s/IF *:LNOT: *:DEF:/ .ifndef/;
88     s/ELSE/ .else/;
89     s/ENDIF/ .endif/;
90
91     if( /\bIF\b/ ) {
92       s/\bIF\b/ .if/;
93       s/=/==/;
94     }
95     if ( $n == 2) {
96         s/\$/\\/g;
97     }
98     if ($n == 1) {
99         s/\$//g;
100         s/label//g;
101     $n = 2;
102       }
103     if ( /MACRO/ ) {
104       s/MACRO *\n/.macro/;
105       $n=1;
106     }
107     if ( /\bMEND\b/ ) {
108       s/\bMEND\b/.endm/;
109       $n=0;
110     }
111
112     # ".rdata" doesn't work in 'as' version 2.13.2, as it is ".rodata" there.
113     #
114     if ( /\bAREA\b/ ) {
115         my $align;
116         $align = "2";
117         if ( /ALIGN=(\d+)/ ) {
118             $align = $1;
119         }
120         if ( /CODE/ ) {
121             $nxstack = 1;
122         }
123         s/^(.+)CODE(.+)READONLY(.*)/    .text/;
124         s/^(.+)DATA(.+)READONLY(.*)/    .section .rdata/;
125         s/^(.+)\|\|\.data\|\|(.+)/    .data/;
126         s/^(.+)\|\|\.bss\|\|(.+)/    .bss/;
127         s/$/;   .p2align $align/;
128         # Enable NEON instructions but don't produce a binary that requires
129         # ARMv7. RVCT does not have equivalent directives, so we just do this
130         # for all CODE areas.
131         if ( /.text/ ) {
132             # Separating .arch, .fpu, etc., by semicolons does not work (gas
133             # thinks the semicolon is part of the arch name, even when there's
134             # whitespace separating them). Sadly this means our line numbers
135             # won't match the original source file (we could use the .line
136             # directive, which is documented to be obsolete, but then gdb will
137             # show the wrong line in the translated source file).
138             s/$/;   .arch armv7-a\n   .fpu neon\n   .object_arch armv4t/;
139         }
140     }
141
142     s/\|\|\.constdata\$(\d+)\|\|/.L_CONST$1/;       # ||.constdata$3||
143     s/\|\|\.bss\$(\d+)\|\|/.L_BSS$1/;               # ||.bss$2||
144     s/\|\|\.data\$(\d+)\|\|/.L_DATA$1/;             # ||.data$2||
145     s/\|\|([a-zA-Z0-9_]+)\@([a-zA-Z0-9_]+)\|\|/@ $&/;
146     s/^(\s+)\%(\s)/    .space $1/;
147
148     s/\|(.+)\.(\d+)\|/\.$1_$2/;                     # |L80.123| -> .L80_123
149     s/\bCODE32\b/.code 32/ && do {$thumb = 0};
150     s/\bCODE16\b/.code 16/ && do {$thumb = 1};
151     if (/\bPROC\b/)
152     {
153         my $prefix;
154         my $proc;
155         /^([A-Za-z_\.]\w+)\b/;
156         $proc = $1;
157         $prefix = "";
158         if ($proc)
159         {
160             $prefix = $prefix.sprintf("\t.type\t%s, %%function; ",$proc);
161             push(@proc_stack, $proc);
162             s/^[A-Za-z_\.]\w+/$&:/;
163         }
164         $prefix = $prefix."\t.thumb_func; " if ($thumb);
165         s/\bPROC\b/@ $&/;
166         $_ = $prefix.$_;
167     }
168     s/^(\s*)(S|Q|SH|U|UQ|UH)ASX\b/$1$2ADDSUBX/;
169     s/^(\s*)(S|Q|SH|U|UQ|UH)SAX\b/$1$2SUBADDX/;
170     if (/\bENDP\b/)
171     {
172         my $proc;
173         s/\bENDP\b/@ $&/;
174         $proc = pop(@proc_stack);
175         $_ = "\t.size $proc, .-$proc".$_ if ($proc);
176     }
177     s/\bSUBT\b/@ $&/;
178     s/\bDATA\b/@ $&/;   # DATA directive is deprecated -- Asm guide, p.7-25
179     s/\bKEEP\b/@ $&/;
180     s/\bEXPORTAS\b/@ $&/;
181     s/\|\|(.)+\bEQU\b/@ $&/;
182     s/\|\|([\w\$]+)\|\|/$1/;
183     s/\bENTRY\b/@ $&/;
184     s/\bASSERT\b/@ $&/;
185     s/\bGBLL\b/@ $&/;
186     s/\bGBLA\b/@ $&/;
187     s/^\W+OPT\b/@ $&/;
188     s/:OR:/|/g;
189     s/:SHL:/<</g;
190     s/:SHR:/>>/g;
191     s/:AND:/&/g;
192     s/:LAND:/&&/g;
193     s/CPSR/cpsr/;
194     s/SPSR/spsr/;
195     s/ALIGN$/.balign 4/;
196     s/ALIGN\s+([0-9x]+)$/.balign $1/;
197     s/psr_cxsf/psr_all/;
198     s/LTORG/.ltorg/;
199     s/^([A-Za-z_]\w*)[ \t]+EQU/ .set $1,/;
200     s/^([A-Za-z_]\w*)[ \t]+SETL/ .set $1,/;
201     s/^([A-Za-z_]\w*)[ \t]+SETA/ .set $1,/;
202     s/^([A-Za-z_]\w*)[ \t]+\*/ .set $1,/;
203
204     #  {PC} + 0xdeadfeed  -->  . + 0xdeadfeed
205     s/\{PC\} \+/ \. +/;
206
207     # Single hex constant on the line !
208     #
209     # >>> NOTE <<<
210     #   Double-precision floats in gcc are always mixed-endian, which means
211     #   bytes in two words are little-endian, but words are big-endian.
212     #   So, 0x0000deadfeed0000 would be stored as 0x0000dead at low address
213     #   and 0xfeed0000 at high address.
214     #
215     s/\bDCFD\b[ \t]+0x([a-fA-F0-9]{8})([a-fA-F0-9]{8})/.long 0x$1, 0x$2/;
216     # Only decimal constants on the line, no hex !
217     s/\bDCFD\b[ \t]+([0-9\.\-]+)/.double $1/;
218
219     # Single hex constant on the line !
220 #    s/\bDCFS\b[ \t]+0x([a-f0-9]{8})([a-f0-9]{8})/.long 0x$1, 0x$2/;
221     # Only decimal constants on the line, no hex !
222 #    s/\bDCFS\b[ \t]+([0-9\.\-]+)/.double $1/;
223     s/\bDCFS[ \t]+0x/.word 0x/;
224     s/\bDCFS\b/.float/;
225
226     s/^([A-Za-z_]\w*)[ \t]+DCD/$1 .word/;
227     s/\bDCD\b/.word/;
228     s/^([A-Za-z_]\w*)[ \t]+DCW/$1 .short/;
229     s/\bDCW\b/.short/;
230     s/^([A-Za-z_]\w*)[ \t]+DCB/$1 .byte/;
231     s/\bDCB\b/.byte/;
232     s/^([A-Za-z_]\w*)[ \t]+\%/.comm $1,/;
233     s/^[A-Za-z_\.]\w+/$&:/;
234     s/^(\d+)/$1:/;
235     s/\%(\d+)/$1b_or_f/;
236     s/\%[Bb](\d+)/$1b/;
237     s/\%[Ff](\d+)/$1f/;
238     s/\%[Ff][Tt](\d+)/$1f/;
239     s/&([\dA-Fa-f]+)/0x$1/;
240     if ( /\b2_[01]+\b/ ) {
241       s/\b2_([01]+)\b/conv$1&&&&/g;
242       while ( /[01][01][01][01]&&&&/ ) {
243         s/0000&&&&/&&&&0/g;
244         s/0001&&&&/&&&&1/g;
245         s/0010&&&&/&&&&2/g;
246         s/0011&&&&/&&&&3/g;
247         s/0100&&&&/&&&&4/g;
248         s/0101&&&&/&&&&5/g;
249         s/0110&&&&/&&&&6/g;
250         s/0111&&&&/&&&&7/g;
251         s/1000&&&&/&&&&8/g;
252         s/1001&&&&/&&&&9/g;
253         s/1010&&&&/&&&&A/g;
254         s/1011&&&&/&&&&B/g;
255         s/1100&&&&/&&&&C/g;
256         s/1101&&&&/&&&&D/g;
257         s/1110&&&&/&&&&E/g;
258         s/1111&&&&/&&&&F/g;
259       }
260       s/000&&&&/&&&&0/g;
261       s/001&&&&/&&&&1/g;
262       s/010&&&&/&&&&2/g;
263       s/011&&&&/&&&&3/g;
264       s/100&&&&/&&&&4/g;
265       s/101&&&&/&&&&5/g;
266       s/110&&&&/&&&&6/g;
267       s/111&&&&/&&&&7/g;
268       s/00&&&&/&&&&0/g;
269       s/01&&&&/&&&&1/g;
270       s/10&&&&/&&&&2/g;
271       s/11&&&&/&&&&3/g;
272       s/0&&&&/&&&&0/g;
273       s/1&&&&/&&&&1/g;
274       s/conv&&&&/0x/g;
275     }
276
277     if ( /commandline/)
278     {
279         if( /-bigend/)
280         {
281             $bigend=1;
282         }
283     }
284
285     if ( /\bDCDU\b/ )
286     {
287         my $cmd=$_;
288         my $value;
289         my $prefix;
290         my $w1;
291         my $w2;
292         my $w3;
293         my $w4;
294
295         s/\s+DCDU\b/@ $&/;
296
297         $cmd =~ /\bDCDU\b\s+0x(\d+)/;
298         $value = $1;
299         $value =~ /(\w\w)(\w\w)(\w\w)(\w\w)/;
300         $w1 = $1;
301         $w2 = $2;
302         $w3 = $3;
303         $w4 = $4;
304
305         if( $bigend ne "")
306         {
307             # big endian
308             $prefix = "\t.byte\t0x".$w1.";".
309                       "\t.byte\t0x".$w2.";".
310                       "\t.byte\t0x".$w3.";".
311                       "\t.byte\t0x".$w4."; ";
312         }
313         else
314         {
315             # little endian
316             $prefix = "\t.byte\t0x".$w4.";".
317                       "\t.byte\t0x".$w3.";".
318                       "\t.byte\t0x".$w2.";".
319                       "\t.byte\t0x".$w1."; ";
320         }
321         $_=$prefix.$_;
322     }
323
324     if ( /\badrl\b/i )
325     {
326         s/\badrl\s+(\w+)\s*,\s*(\w+)/ldr $1,=$2/i;
327         $addPadding = 1;
328     }
329     s/\bEND\b/@ END/;
330 } continue {
331     printf ("%s", $_) if $printit;
332     if ($addPadding != 0)
333     {
334         printf ("   mov r0,r0\n");
335         $addPadding = 0;
336     }
337 }
338 #If we had a code section, mark that this object doesn't need an executable
339 # stack.
340 if ($nxstack) {
341     printf ("    .section\t.note.GNU-stack,\"\",\%\%progbits\n");
342 }