|  | #!/usr/bin/env perl | 
|  | ## | 
|  | ##  Copyright (c) 2010 The WebM project authors. All Rights Reserved. | 
|  | ## | 
|  | ##  Use of this source code is governed by a BSD-style license | 
|  | ##  that can be found in the LICENSE file in the root of the source | 
|  | ##  tree. An additional intellectual property rights grant can be found | 
|  | ##  in the file PATENTS.  All contributing project authors may | 
|  | ##  be found in the AUTHORS file in the root of the source tree. | 
|  | ## | 
|  |  | 
|  |  | 
|  | # ads2gas.pl | 
|  | # Author: Eric Fung (efung (at) acm.org) | 
|  | # | 
|  | # Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format | 
|  | # | 
|  | # Usage: cat inputfile | perl ads2gas.pl > outputfile | 
|  | # | 
|  |  | 
|  | use FindBin; | 
|  | use lib $FindBin::Bin; | 
|  | use thumb; | 
|  |  | 
|  | my $thumb = 0; | 
|  |  | 
|  | foreach my $arg (@ARGV) { | 
|  | $thumb = 1 if ($arg eq "-thumb"); | 
|  | } | 
|  |  | 
|  | print "@ This file was created from a .asm file\n"; | 
|  | print "@  using the ads2gas.pl script.\n"; | 
|  | print "\t.equ DO1STROUNDING, 0\n"; | 
|  | if ($thumb) { | 
|  | print "\t.syntax unified\n"; | 
|  | print "\t.thumb\n"; | 
|  | } | 
|  |  | 
|  | # Stack of procedure names. | 
|  | @proc_stack = (); | 
|  |  | 
|  | while (<STDIN>) | 
|  | { | 
|  | undef $comment; | 
|  | undef $line; | 
|  | $comment_char = ";"; | 
|  | $comment_sub = "@"; | 
|  |  | 
|  | # Handle comments. | 
|  | if (/$comment_char/) | 
|  | { | 
|  | $comment = ""; | 
|  | ($line, $comment) = /(.*?)$comment_char(.*)/; | 
|  | $_ = $line; | 
|  | } | 
|  |  | 
|  | # Load and store alignment | 
|  | s/@/,:/g; | 
|  |  | 
|  | # Hexadecimal constants prefaced by 0x | 
|  | s/#&/#0x/g; | 
|  |  | 
|  | # Convert :OR: to | | 
|  | s/:OR:/ | /g; | 
|  |  | 
|  | # Convert :AND: to & | 
|  | s/:AND:/ & /g; | 
|  |  | 
|  | # Convert :NOT: to ~ | 
|  | s/:NOT:/ ~ /g; | 
|  |  | 
|  | # Convert :SHL: to << | 
|  | s/:SHL:/ << /g; | 
|  |  | 
|  | # Convert :SHR: to >> | 
|  | s/:SHR:/ >> /g; | 
|  |  | 
|  | # Convert ELSE to .else | 
|  | s/\bELSE\b/.else/g; | 
|  |  | 
|  | # Convert ENDIF to .endif | 
|  | s/\bENDIF\b/.endif/g; | 
|  |  | 
|  | # Convert ELSEIF to .elseif | 
|  | s/\bELSEIF\b/.elseif/g; | 
|  |  | 
|  | # Convert LTORG to .ltorg | 
|  | s/\bLTORG\b/.ltorg/g; | 
|  |  | 
|  | # Convert endfunc to nothing. | 
|  | s/\bendfunc\b//ig; | 
|  |  | 
|  | # Convert FUNCTION to nothing. | 
|  | s/\bFUNCTION\b//g; | 
|  | s/\bfunction\b//g; | 
|  |  | 
|  | s/\bENTRY\b//g; | 
|  | s/\bMSARMASM\b/0/g; | 
|  | s/^\s+end\s+$//g; | 
|  |  | 
|  | # Convert IF :DEF:to .if | 
|  | # gcc doesn't have the ability to do a conditional | 
|  | # if defined variable that is set by IF :DEF: on | 
|  | # armasm, so convert it to a normal .if and then | 
|  | # make sure to define a value elesewhere | 
|  | if (s/\bIF :DEF:\b/.if /g) | 
|  | { | 
|  | s/=/==/g; | 
|  | } | 
|  |  | 
|  | # Convert IF to .if | 
|  | if (s/\bIF\b/.if/g) | 
|  | { | 
|  | s/=+/==/g; | 
|  | } | 
|  |  | 
|  | # Convert INCLUDE to .INCLUDE "file" | 
|  | s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/; | 
|  |  | 
|  | # Code directive (ARM vs Thumb) | 
|  | s/CODE([0-9][0-9])/.code $1/; | 
|  |  | 
|  | # No AREA required | 
|  | # But ALIGNs in AREA must be obeyed | 
|  | s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/; | 
|  | # If no ALIGN, strip the AREA and align to 4 bytes | 
|  | s/^\s*AREA.*$/.text\n.p2align 2/; | 
|  |  | 
|  | # DCD to .word | 
|  | # This one is for incoming symbols | 
|  | s/DCD\s+\|(\w*)\|/.long $1/; | 
|  |  | 
|  | # DCW to .short | 
|  | s/DCW\s+\|(\w*)\|/.short $1/; | 
|  | s/DCW(.*)/.short $1/; | 
|  |  | 
|  | # Constants defined in scope | 
|  | s/DCD(.*)/.long $1/; | 
|  | s/DCB(.*)/.byte $1/; | 
|  |  | 
|  | # RN to .req | 
|  | if (s/RN\s+([Rr]\d+|lr)/.req $1/) | 
|  | { | 
|  | print; | 
|  | print "$comment_sub$comment\n" if defined $comment; | 
|  | next; | 
|  | } | 
|  |  | 
|  | # Make function visible to linker, and make additional symbol with | 
|  | # prepended underscore | 
|  | s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/; | 
|  | s/IMPORT\s+\|([\$\w]*)\|/.global $1/; | 
|  |  | 
|  | s/EXPORT\s+([\$\w]*)/.global $1/; | 
|  | s/export\s+([\$\w]*)/.global $1/; | 
|  |  | 
|  | # No vertical bars required; make additional symbol with prepended | 
|  | # underscore | 
|  | s/^\|(\$?\w+)\|/_$1\n\t$1:/g; | 
|  |  | 
|  | # Labels need trailing colon | 
|  | #   s/^(\w+)/$1:/ if !/EQU/; | 
|  | # put the colon at the end of the line in the macro | 
|  | s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/; | 
|  |  | 
|  | # ALIGN directive | 
|  | s/\bALIGN\b/.balign/g; | 
|  |  | 
|  | if ($thumb) { | 
|  | # ARM code - we force everything to thumb with the declaration in the header | 
|  | s/\sARM//g; | 
|  | } else { | 
|  | # ARM code | 
|  | s/\sARM/.arm/g; | 
|  | } | 
|  |  | 
|  | # push/pop | 
|  | s/(push\s+)(r\d+)/stmdb sp\!, \{$2\}/g; | 
|  | s/(pop\s+)(r\d+)/ldmia sp\!, \{$2\}/g; | 
|  |  | 
|  | # NEON code | 
|  | s/(vld1.\d+\s+)(q\d+)/$1\{$2\}/g; | 
|  | s/(vtbl.\d+\s+[^,]+),([^,]+)/$1,\{$2\}/g; | 
|  |  | 
|  | if ($thumb) { | 
|  | thumb::FixThumbInstructions($_, 0); | 
|  | } | 
|  |  | 
|  | # eabi_attributes numerical equivalents can be found in the | 
|  | # "ARM IHI 0045C" document. | 
|  |  | 
|  | # REQUIRE8 Stack is required to be 8-byte aligned | 
|  | s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g; | 
|  |  | 
|  | # PRESERVE8 Stack 8-byte align is preserved | 
|  | s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g; | 
|  |  | 
|  | # Use PROC and ENDP to give the symbols a .size directive. | 
|  | # This makes them show up properly in debugging tools like gdb and valgrind. | 
|  | if (/\bPROC\b/) | 
|  | { | 
|  | my $proc; | 
|  | /^_([\.0-9A-Z_a-z]\w+)\b/; | 
|  | $proc = $1; | 
|  | push(@proc_stack, $proc) if ($proc); | 
|  | s/\bPROC\b/@ $&/; | 
|  | } | 
|  | if (/\bENDP\b/) | 
|  | { | 
|  | my $proc; | 
|  | s/\bENDP\b/@ $&/; | 
|  | $proc = pop(@proc_stack); | 
|  | $_ = "\t.size $proc, .-$proc".$_ if ($proc); | 
|  | } | 
|  |  | 
|  | # EQU directive | 
|  | s/(\S+\s+)EQU(\s+\S+)/.equ $1, $2/; | 
|  |  | 
|  | # Begin macro definition | 
|  | if (/\bMACRO\b/) { | 
|  | $_ = <STDIN>; | 
|  | s/^/.macro/; | 
|  | s/\$//g;                # remove formal param reference | 
|  | s/;/@/g;                # change comment characters | 
|  | } | 
|  |  | 
|  | # For macros, use \ to reference formal params | 
|  | s/\$/\\/g;                  # End macro definition | 
|  | s/\bMEND\b/.endm/;              # No need to tell it where to stop assembling | 
|  | next if /^\s*END\s*$/; | 
|  | print; | 
|  | print "$comment_sub$comment\n" if defined $comment; | 
|  | } | 
|  |  | 
|  | # Mark that this object doesn't need an executable stack. | 
|  | printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n"); |