1#!/usr/bin/env perl 2## 3## Copyright (c) 2010 The WebM project authors. All Rights Reserved. 4## 5## Use of this source code is governed by a BSD-style license 6## that can be found in the LICENSE file in the root of the source 7## tree. An additional intellectual property rights grant can be found 8## in the file PATENTS. All contributing project authors may 9## be found in the AUTHORS file in the root of the source tree. 10## 11 12 13# ads2gas.pl 14# Author: Eric Fung (efung (at) acm.org) 15# 16# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format 17# 18# Usage: cat inputfile | perl ads2gas.pl > outputfile 19# 20 21use FindBin; 22use lib $FindBin::Bin; 23use thumb; 24 25my $thumb = 0; 26my $elf = 1; 27 28foreach my $arg (@ARGV) { 29 $thumb = 1 if ($arg eq "-thumb"); 30 $elf = 0 if ($arg eq "-noelf"); 31} 32 33print "@ This file was created from a .asm file\n"; 34print "@ using the ads2gas.pl script.\n"; 35print "\t.equ DO1STROUNDING, 0\n"; 36print "\t.syntax unified\n"; 37if ($thumb) { 38 print "\t.thumb\n"; 39} 40 41# Stack of procedure names. 42@proc_stack = (); 43 44while (<STDIN>) 45{ 46 undef $comment; 47 undef $line; 48 $comment_char = ";"; 49 $comment_sub = "@"; 50 51 # Handle comments. 52 if (/$comment_char/) 53 { 54 $comment = ""; 55 ($line, $comment) = /(.*?)$comment_char(.*)/; 56 $_ = $line; 57 } 58 59 # Load and store alignment 60 s/@/,:/g; 61 62 # Hexadecimal constants prefaced by 0x 63 s/#&/#0x/g; 64 65 # Convert :OR: to | 66 s/:OR:/ | /g; 67 68 # Convert :AND: to & 69 s/:AND:/ & /g; 70 71 # Convert :NOT: to ~ 72 s/:NOT:/ ~ /g; 73 74 # Convert :SHL: to << 75 s/:SHL:/ << /g; 76 77 # Convert :SHR: to >> 78 s/:SHR:/ >> /g; 79 80 # Convert ELSE to .else 81 s/\bELSE\b/.else/g; 82 83 # Convert ENDIF to .endif 84 s/\bENDIF\b/.endif/g; 85 86 # Convert ELSEIF to .elseif 87 s/\bELSEIF\b/.elseif/g; 88 89 # Convert LTORG to .ltorg 90 s/\bLTORG\b/.ltorg/g; 91 92 # Convert endfunc to nothing. 93 s/\bendfunc\b//ig; 94 95 # Convert FUNCTION to nothing. 96 s/\bFUNCTION\b//g; 97 s/\bfunction\b//g; 98 99 s/\bENTRY\b//g; 100 s/\bMSARMASM\b/0/g; 101 s/^\s+end\s+$//g; 102 103 # Convert IF :DEF:to .if 104 # gcc doesn't have the ability to do a conditional 105 # if defined variable that is set by IF :DEF: on 106 # armasm, so convert it to a normal .if and then 107 # make sure to define a value elesewhere 108 if (s/\bIF :DEF:\b/.if /g) 109 { 110 s/=/==/g; 111 } 112 113 # Convert IF to .if 114 if (s/\bIF\b/.if/g) 115 { 116 s/=+/==/g; 117 } 118 119 # Convert INCLUDE to .INCLUDE "file" 120 s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/; 121 122 # Code directive (ARM vs Thumb) 123 s/CODE([0-9][0-9])/.code $1/; 124 125 # No AREA required 126 # But ALIGNs in AREA must be obeyed 127 s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/; 128 # If no ALIGN, strip the AREA and align to 4 bytes 129 s/^\s*AREA.*$/.text\n.p2align 2/; 130 131 # DCD to .word 132 # This one is for incoming symbols 133 s/DCD\s+\|(\w*)\|/.long $1/; 134 135 # DCW to .short 136 s/DCW\s+\|(\w*)\|/.short $1/; 137 s/DCW(.*)/.short $1/; 138 139 # Constants defined in scope 140 s/DCD(.*)/.long $1/; 141 s/DCB(.*)/.byte $1/; 142 143 # Make function visible to linker, and make additional symbol with 144 # prepended underscore 145 if ($elf) { 146 s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/; 147 } else { 148 s/EXPORT\s+\|([\$\w]*)\|/.global $1/; 149 } 150 s/IMPORT\s+\|([\$\w]*)\|/.global $1/; 151 152 s/EXPORT\s+([\$\w]*)/.global $1/; 153 s/export\s+([\$\w]*)/.global $1/; 154 155 # No vertical bars required; make additional symbol with prepended 156 # underscore 157 s/^\|(\$?\w+)\|/_$1\n\t$1:/g; 158 159 # Labels need trailing colon 160# s/^(\w+)/$1:/ if !/EQU/; 161 # put the colon at the end of the line in the macro 162 s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/; 163 164 # ALIGN directive 165 s/\bALIGN\b/.balign/g; 166 167 if ($thumb) { 168 # ARM code - we force everything to thumb with the declaration in the header 169 s/\sARM//g; 170 } else { 171 # ARM code 172 s/\sARM/.arm/g; 173 } 174 175 # push/pop 176 s/(push\s+)(r\d+)/stmdb sp\!, \{$2\}/g; 177 s/(pop\s+)(r\d+)/ldmia sp\!, \{$2\}/g; 178 179 # NEON code 180 s/(vld1.\d+\s+)(q\d+)/$1\{$2\}/g; 181 s/(vtbl.\d+\s+[^,]+),([^,]+)/$1,\{$2\}/g; 182 183 if ($thumb) { 184 thumb::FixThumbInstructions($_, 0); 185 } 186 187 # eabi_attributes numerical equivalents can be found in the 188 # "ARM IHI 0045C" document. 189 190 if ($elf) { 191 # REQUIRE8 Stack is required to be 8-byte aligned 192 s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g; 193 194 # PRESERVE8 Stack 8-byte align is preserved 195 s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g; 196 } else { 197 s/\sREQUIRE8//; 198 s/\sPRESERVE8//; 199 } 200 201 # Use PROC and ENDP to give the symbols a .size directive. 202 # This makes them show up properly in debugging tools like gdb and valgrind. 203 if (/\bPROC\b/) 204 { 205 my $proc; 206 /^_([\.0-9A-Z_a-z]\w+)\b/; 207 $proc = $1; 208 push(@proc_stack, $proc) if ($proc); 209 s/\bPROC\b/@ $&/; 210 } 211 if (/\bENDP\b/) 212 { 213 my $proc; 214 s/\bENDP\b/@ $&/; 215 $proc = pop(@proc_stack); 216 $_ = "\t.size $proc, .-$proc".$_ if ($proc and $elf); 217 } 218 219 # EQU directive 220 s/(\S+\s+)EQU(\s+\S+)/.equ $1, $2/; 221 222 # Begin macro definition 223 if (/\bMACRO\b/) { 224 $_ = <STDIN>; 225 s/^/.macro/; 226 s/\$//g; # remove formal param reference 227 s/;/@/g; # change comment characters 228 } 229 230 # For macros, use \ to reference formal params 231 s/\$/\\/g; # End macro definition 232 s/\bMEND\b/.endm/; # No need to tell it where to stop assembling 233 next if /^\s*END\s*$/; 234 print; 235 print "$comment_sub$comment\n" if defined $comment; 236} 237 238# Mark that this object doesn't need an executable stack. 239printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n") if $elf; 240