1b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#!/usr/bin/env perl
21b362b15af34006e6a11974088a46d42b903418eJohann##
31b362b15af34006e6a11974088a46d42b903418eJohann##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
41b362b15af34006e6a11974088a46d42b903418eJohann##
51b362b15af34006e6a11974088a46d42b903418eJohann##  Use of this source code is governed by a BSD-style license
61b362b15af34006e6a11974088a46d42b903418eJohann##  that can be found in the LICENSE file in the root of the source
71b362b15af34006e6a11974088a46d42b903418eJohann##  tree. An additional intellectual property rights grant can be found
81b362b15af34006e6a11974088a46d42b903418eJohann##  in the file PATENTS.  All contributing project authors may
91b362b15af34006e6a11974088a46d42b903418eJohann##  be found in the AUTHORS file in the root of the source tree.
101b362b15af34006e6a11974088a46d42b903418eJohann##
111b362b15af34006e6a11974088a46d42b903418eJohann
121b362b15af34006e6a11974088a46d42b903418eJohann
131b362b15af34006e6a11974088a46d42b903418eJohann# ads2gas.pl
141b362b15af34006e6a11974088a46d42b903418eJohann# Author: Eric Fung (efung (at) acm.org)
151b362b15af34006e6a11974088a46d42b903418eJohann#
161b362b15af34006e6a11974088a46d42b903418eJohann# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
171b362b15af34006e6a11974088a46d42b903418eJohann#
181b362b15af34006e6a11974088a46d42b903418eJohann# Usage: cat inputfile | perl ads2gas.pl > outputfile
191b362b15af34006e6a11974088a46d42b903418eJohann#
20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuanguse FindBin;
22ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuanguse lib $FindBin::Bin;
23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuanguse thumb;
24ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangmy $thumb = 0;
26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
27ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangforeach my $arg (@ARGV) {
28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    $thumb = 1 if ($arg eq "-thumb");
29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
311b362b15af34006e6a11974088a46d42b903418eJohannprint "@ This file was created from a .asm file\n";
321b362b15af34006e6a11974088a46d42b903418eJohannprint "@  using the ads2gas.pl script.\n";
331b362b15af34006e6a11974088a46d42b903418eJohannprint "\t.equ DO1STROUNDING, 0\n";
34ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangif ($thumb) {
35ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    print "\t.syntax unified\n";
36ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    print "\t.thumb\n";
37ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
381b362b15af34006e6a11974088a46d42b903418eJohann
391b362b15af34006e6a11974088a46d42b903418eJohann# Stack of procedure names.
401b362b15af34006e6a11974088a46d42b903418eJohann@proc_stack = ();
411b362b15af34006e6a11974088a46d42b903418eJohann
421b362b15af34006e6a11974088a46d42b903418eJohannwhile (<STDIN>)
431b362b15af34006e6a11974088a46d42b903418eJohann{
441b362b15af34006e6a11974088a46d42b903418eJohann    undef $comment;
451b362b15af34006e6a11974088a46d42b903418eJohann    undef $line;
461b362b15af34006e6a11974088a46d42b903418eJohann    $comment_char = ";";
471b362b15af34006e6a11974088a46d42b903418eJohann    $comment_sub = "@";
481b362b15af34006e6a11974088a46d42b903418eJohann
491b362b15af34006e6a11974088a46d42b903418eJohann    # Handle comments.
501b362b15af34006e6a11974088a46d42b903418eJohann    if (/$comment_char/)
511b362b15af34006e6a11974088a46d42b903418eJohann    {
521b362b15af34006e6a11974088a46d42b903418eJohann      $comment = "";
531b362b15af34006e6a11974088a46d42b903418eJohann      ($line, $comment) = /(.*?)$comment_char(.*)/;
541b362b15af34006e6a11974088a46d42b903418eJohann      $_ = $line;
551b362b15af34006e6a11974088a46d42b903418eJohann    }
561b362b15af34006e6a11974088a46d42b903418eJohann
571b362b15af34006e6a11974088a46d42b903418eJohann    # Load and store alignment
581b362b15af34006e6a11974088a46d42b903418eJohann    s/@/,:/g;
591b362b15af34006e6a11974088a46d42b903418eJohann
601b362b15af34006e6a11974088a46d42b903418eJohann    # Hexadecimal constants prefaced by 0x
611b362b15af34006e6a11974088a46d42b903418eJohann    s/#&/#0x/g;
621b362b15af34006e6a11974088a46d42b903418eJohann
631b362b15af34006e6a11974088a46d42b903418eJohann    # Convert :OR: to |
641b362b15af34006e6a11974088a46d42b903418eJohann    s/:OR:/ | /g;
651b362b15af34006e6a11974088a46d42b903418eJohann
661b362b15af34006e6a11974088a46d42b903418eJohann    # Convert :AND: to &
671b362b15af34006e6a11974088a46d42b903418eJohann    s/:AND:/ & /g;
681b362b15af34006e6a11974088a46d42b903418eJohann
691b362b15af34006e6a11974088a46d42b903418eJohann    # Convert :NOT: to ~
701b362b15af34006e6a11974088a46d42b903418eJohann    s/:NOT:/ ~ /g;
711b362b15af34006e6a11974088a46d42b903418eJohann
721b362b15af34006e6a11974088a46d42b903418eJohann    # Convert :SHL: to <<
731b362b15af34006e6a11974088a46d42b903418eJohann    s/:SHL:/ << /g;
741b362b15af34006e6a11974088a46d42b903418eJohann
751b362b15af34006e6a11974088a46d42b903418eJohann    # Convert :SHR: to >>
761b362b15af34006e6a11974088a46d42b903418eJohann    s/:SHR:/ >> /g;
771b362b15af34006e6a11974088a46d42b903418eJohann
781b362b15af34006e6a11974088a46d42b903418eJohann    # Convert ELSE to .else
791b362b15af34006e6a11974088a46d42b903418eJohann    s/\bELSE\b/.else/g;
801b362b15af34006e6a11974088a46d42b903418eJohann
811b362b15af34006e6a11974088a46d42b903418eJohann    # Convert ENDIF to .endif
821b362b15af34006e6a11974088a46d42b903418eJohann    s/\bENDIF\b/.endif/g;
831b362b15af34006e6a11974088a46d42b903418eJohann
841b362b15af34006e6a11974088a46d42b903418eJohann    # Convert ELSEIF to .elseif
851b362b15af34006e6a11974088a46d42b903418eJohann    s/\bELSEIF\b/.elseif/g;
861b362b15af34006e6a11974088a46d42b903418eJohann
871b362b15af34006e6a11974088a46d42b903418eJohann    # Convert LTORG to .ltorg
881b362b15af34006e6a11974088a46d42b903418eJohann    s/\bLTORG\b/.ltorg/g;
891b362b15af34006e6a11974088a46d42b903418eJohann
901b362b15af34006e6a11974088a46d42b903418eJohann    # Convert endfunc to nothing.
911b362b15af34006e6a11974088a46d42b903418eJohann    s/\bendfunc\b//ig;
921b362b15af34006e6a11974088a46d42b903418eJohann
931b362b15af34006e6a11974088a46d42b903418eJohann    # Convert FUNCTION to nothing.
941b362b15af34006e6a11974088a46d42b903418eJohann    s/\bFUNCTION\b//g;
951b362b15af34006e6a11974088a46d42b903418eJohann    s/\bfunction\b//g;
961b362b15af34006e6a11974088a46d42b903418eJohann
971b362b15af34006e6a11974088a46d42b903418eJohann    s/\bENTRY\b//g;
981b362b15af34006e6a11974088a46d42b903418eJohann    s/\bMSARMASM\b/0/g;
991b362b15af34006e6a11974088a46d42b903418eJohann    s/^\s+end\s+$//g;
1001b362b15af34006e6a11974088a46d42b903418eJohann
1011b362b15af34006e6a11974088a46d42b903418eJohann    # Convert IF :DEF:to .if
1021b362b15af34006e6a11974088a46d42b903418eJohann    # gcc doesn't have the ability to do a conditional
1031b362b15af34006e6a11974088a46d42b903418eJohann    # if defined variable that is set by IF :DEF: on
1041b362b15af34006e6a11974088a46d42b903418eJohann    # armasm, so convert it to a normal .if and then
1051b362b15af34006e6a11974088a46d42b903418eJohann    # make sure to define a value elesewhere
1061b362b15af34006e6a11974088a46d42b903418eJohann    if (s/\bIF :DEF:\b/.if /g)
1071b362b15af34006e6a11974088a46d42b903418eJohann    {
1081b362b15af34006e6a11974088a46d42b903418eJohann        s/=/==/g;
1091b362b15af34006e6a11974088a46d42b903418eJohann    }
1101b362b15af34006e6a11974088a46d42b903418eJohann
1111b362b15af34006e6a11974088a46d42b903418eJohann    # Convert IF to .if
1121b362b15af34006e6a11974088a46d42b903418eJohann    if (s/\bIF\b/.if/g)
1131b362b15af34006e6a11974088a46d42b903418eJohann    {
1141b362b15af34006e6a11974088a46d42b903418eJohann        s/=+/==/g;
1151b362b15af34006e6a11974088a46d42b903418eJohann    }
1161b362b15af34006e6a11974088a46d42b903418eJohann
1171b362b15af34006e6a11974088a46d42b903418eJohann    # Convert INCLUDE to .INCLUDE "file"
1181b362b15af34006e6a11974088a46d42b903418eJohann    s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/;
1191b362b15af34006e6a11974088a46d42b903418eJohann
1201b362b15af34006e6a11974088a46d42b903418eJohann    # Code directive (ARM vs Thumb)
1211b362b15af34006e6a11974088a46d42b903418eJohann    s/CODE([0-9][0-9])/.code $1/;
1221b362b15af34006e6a11974088a46d42b903418eJohann
1231b362b15af34006e6a11974088a46d42b903418eJohann    # No AREA required
1241b362b15af34006e6a11974088a46d42b903418eJohann    # But ALIGNs in AREA must be obeyed
1251b362b15af34006e6a11974088a46d42b903418eJohann    s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
1261b362b15af34006e6a11974088a46d42b903418eJohann    # If no ALIGN, strip the AREA and align to 4 bytes
1271b362b15af34006e6a11974088a46d42b903418eJohann    s/^\s*AREA.*$/.text\n.p2align 2/;
1281b362b15af34006e6a11974088a46d42b903418eJohann
1291b362b15af34006e6a11974088a46d42b903418eJohann    # DCD to .word
1301b362b15af34006e6a11974088a46d42b903418eJohann    # This one is for incoming symbols
1311b362b15af34006e6a11974088a46d42b903418eJohann    s/DCD\s+\|(\w*)\|/.long $1/;
1321b362b15af34006e6a11974088a46d42b903418eJohann
1331b362b15af34006e6a11974088a46d42b903418eJohann    # DCW to .short
1341b362b15af34006e6a11974088a46d42b903418eJohann    s/DCW\s+\|(\w*)\|/.short $1/;
1351b362b15af34006e6a11974088a46d42b903418eJohann    s/DCW(.*)/.short $1/;
1361b362b15af34006e6a11974088a46d42b903418eJohann
1371b362b15af34006e6a11974088a46d42b903418eJohann    # Constants defined in scope
1381b362b15af34006e6a11974088a46d42b903418eJohann    s/DCD(.*)/.long $1/;
1391b362b15af34006e6a11974088a46d42b903418eJohann    s/DCB(.*)/.byte $1/;
1401b362b15af34006e6a11974088a46d42b903418eJohann
1411b362b15af34006e6a11974088a46d42b903418eJohann    # RN to .req
1421b362b15af34006e6a11974088a46d42b903418eJohann    if (s/RN\s+([Rr]\d+|lr)/.req $1/)
1431b362b15af34006e6a11974088a46d42b903418eJohann    {
1441b362b15af34006e6a11974088a46d42b903418eJohann        print;
1451b362b15af34006e6a11974088a46d42b903418eJohann        print "$comment_sub$comment\n" if defined $comment;
1461b362b15af34006e6a11974088a46d42b903418eJohann        next;
1471b362b15af34006e6a11974088a46d42b903418eJohann    }
1481b362b15af34006e6a11974088a46d42b903418eJohann
1491b362b15af34006e6a11974088a46d42b903418eJohann    # Make function visible to linker, and make additional symbol with
1501b362b15af34006e6a11974088a46d42b903418eJohann    # prepended underscore
1511b362b15af34006e6a11974088a46d42b903418eJohann    s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
1521b362b15af34006e6a11974088a46d42b903418eJohann    s/IMPORT\s+\|([\$\w]*)\|/.global $1/;
1531b362b15af34006e6a11974088a46d42b903418eJohann
1541b362b15af34006e6a11974088a46d42b903418eJohann    s/EXPORT\s+([\$\w]*)/.global $1/;
1551b362b15af34006e6a11974088a46d42b903418eJohann    s/export\s+([\$\w]*)/.global $1/;
1561b362b15af34006e6a11974088a46d42b903418eJohann
1571b362b15af34006e6a11974088a46d42b903418eJohann    # No vertical bars required; make additional symbol with prepended
1581b362b15af34006e6a11974088a46d42b903418eJohann    # underscore
1591b362b15af34006e6a11974088a46d42b903418eJohann    s/^\|(\$?\w+)\|/_$1\n\t$1:/g;
1601b362b15af34006e6a11974088a46d42b903418eJohann
1611b362b15af34006e6a11974088a46d42b903418eJohann    # Labels need trailing colon
1621b362b15af34006e6a11974088a46d42b903418eJohann#   s/^(\w+)/$1:/ if !/EQU/;
1631b362b15af34006e6a11974088a46d42b903418eJohann    # put the colon at the end of the line in the macro
1641b362b15af34006e6a11974088a46d42b903418eJohann    s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
1651b362b15af34006e6a11974088a46d42b903418eJohann
1661b362b15af34006e6a11974088a46d42b903418eJohann    # ALIGN directive
1671b362b15af34006e6a11974088a46d42b903418eJohann    s/\bALIGN\b/.balign/g;
1681b362b15af34006e6a11974088a46d42b903418eJohann
169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if ($thumb) {
170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # ARM code - we force everything to thumb with the declaration in the header
171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        s/\sARM//g;
172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    } else {
173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # ARM code
174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        s/\sARM/.arm/g;
175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
1761b362b15af34006e6a11974088a46d42b903418eJohann
1771b362b15af34006e6a11974088a46d42b903418eJohann    # push/pop
1781b362b15af34006e6a11974088a46d42b903418eJohann    s/(push\s+)(r\d+)/stmdb sp\!, \{$2\}/g;
1791b362b15af34006e6a11974088a46d42b903418eJohann    s/(pop\s+)(r\d+)/ldmia sp\!, \{$2\}/g;
1801b362b15af34006e6a11974088a46d42b903418eJohann
1811b362b15af34006e6a11974088a46d42b903418eJohann    # NEON code
1821b362b15af34006e6a11974088a46d42b903418eJohann    s/(vld1.\d+\s+)(q\d+)/$1\{$2\}/g;
1831b362b15af34006e6a11974088a46d42b903418eJohann    s/(vtbl.\d+\s+[^,]+),([^,]+)/$1,\{$2\}/g;
1841b362b15af34006e6a11974088a46d42b903418eJohann
185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if ($thumb) {
186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        thumb::FixThumbInstructions($_, 0);
187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
188ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1891b362b15af34006e6a11974088a46d42b903418eJohann    # eabi_attributes numerical equivalents can be found in the
1901b362b15af34006e6a11974088a46d42b903418eJohann    # "ARM IHI 0045C" document.
1911b362b15af34006e6a11974088a46d42b903418eJohann
1921b362b15af34006e6a11974088a46d42b903418eJohann    # REQUIRE8 Stack is required to be 8-byte aligned
1931b362b15af34006e6a11974088a46d42b903418eJohann    s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
1941b362b15af34006e6a11974088a46d42b903418eJohann
1951b362b15af34006e6a11974088a46d42b903418eJohann    # PRESERVE8 Stack 8-byte align is preserved
1961b362b15af34006e6a11974088a46d42b903418eJohann    s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
1971b362b15af34006e6a11974088a46d42b903418eJohann
1981b362b15af34006e6a11974088a46d42b903418eJohann    # Use PROC and ENDP to give the symbols a .size directive.
1991b362b15af34006e6a11974088a46d42b903418eJohann    # This makes them show up properly in debugging tools like gdb and valgrind.
2001b362b15af34006e6a11974088a46d42b903418eJohann    if (/\bPROC\b/)
2011b362b15af34006e6a11974088a46d42b903418eJohann    {
2021b362b15af34006e6a11974088a46d42b903418eJohann        my $proc;
2031b362b15af34006e6a11974088a46d42b903418eJohann        /^_([\.0-9A-Z_a-z]\w+)\b/;
2041b362b15af34006e6a11974088a46d42b903418eJohann        $proc = $1;
2051b362b15af34006e6a11974088a46d42b903418eJohann        push(@proc_stack, $proc) if ($proc);
2061b362b15af34006e6a11974088a46d42b903418eJohann        s/\bPROC\b/@ $&/;
2071b362b15af34006e6a11974088a46d42b903418eJohann    }
2081b362b15af34006e6a11974088a46d42b903418eJohann    if (/\bENDP\b/)
2091b362b15af34006e6a11974088a46d42b903418eJohann    {
2101b362b15af34006e6a11974088a46d42b903418eJohann        my $proc;
2111b362b15af34006e6a11974088a46d42b903418eJohann        s/\bENDP\b/@ $&/;
2121b362b15af34006e6a11974088a46d42b903418eJohann        $proc = pop(@proc_stack);
2131b362b15af34006e6a11974088a46d42b903418eJohann        $_ = "\t.size $proc, .-$proc".$_ if ($proc);
2141b362b15af34006e6a11974088a46d42b903418eJohann    }
2151b362b15af34006e6a11974088a46d42b903418eJohann
2161b362b15af34006e6a11974088a46d42b903418eJohann    # EQU directive
2171b362b15af34006e6a11974088a46d42b903418eJohann    s/(\S+\s+)EQU(\s+\S+)/.equ $1, $2/;
2181b362b15af34006e6a11974088a46d42b903418eJohann
2191b362b15af34006e6a11974088a46d42b903418eJohann    # Begin macro definition
2201b362b15af34006e6a11974088a46d42b903418eJohann    if (/\bMACRO\b/) {
2211b362b15af34006e6a11974088a46d42b903418eJohann        $_ = <STDIN>;
2221b362b15af34006e6a11974088a46d42b903418eJohann        s/^/.macro/;
2231b362b15af34006e6a11974088a46d42b903418eJohann        s/\$//g;                # remove formal param reference
2241b362b15af34006e6a11974088a46d42b903418eJohann        s/;/@/g;                # change comment characters
2251b362b15af34006e6a11974088a46d42b903418eJohann    }
2261b362b15af34006e6a11974088a46d42b903418eJohann
2271b362b15af34006e6a11974088a46d42b903418eJohann    # For macros, use \ to reference formal params
2281b362b15af34006e6a11974088a46d42b903418eJohann    s/\$/\\/g;                  # End macro definition
2291b362b15af34006e6a11974088a46d42b903418eJohann    s/\bMEND\b/.endm/;              # No need to tell it where to stop assembling
2301b362b15af34006e6a11974088a46d42b903418eJohann    next if /^\s*END\s*$/;
2311b362b15af34006e6a11974088a46d42b903418eJohann    print;
2321b362b15af34006e6a11974088a46d42b903418eJohann    print "$comment_sub$comment\n" if defined $comment;
2331b362b15af34006e6a11974088a46d42b903418eJohann}
2341b362b15af34006e6a11974088a46d42b903418eJohann
2351b362b15af34006e6a11974088a46d42b903418eJohann# Mark that this object doesn't need an executable stack.
2361b362b15af34006e6a11974088a46d42b903418eJohannprintf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n");
237