| #!/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"); |