125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#!/usr/bin/perl 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# Copyright (C) 2002-2013 Xiph.org Foundation 325b3c049e70834cf33790a28643ab058b507b35cBen Cheng# 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng# Redistribution and use in source and binary forms, with or without 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# modification, are permitted provided that the following conditions 625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# are met: 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# - Redistributions of source code must retain the above copyright 925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# notice, this list of conditions and the following disclaimer. 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# 1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng# - Redistributions in binary form must reproduce the above copyright 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# notice, this list of conditions and the following disclaimer in the 1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng# documentation and/or other materials provided with the distribution. 1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng# 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2725b3c049e70834cf33790a28643ab058b507b35cBen Chengmy $bigend; # little/big endian 2825b3c049e70834cf33790a28643ab058b507b35cBen Chengmy $nxstack; 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng$nxstack = 0; 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3225b3c049e70834cf33790a28643ab058b507b35cBen Chengeval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}' 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if $running_under_some_shell; 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3525b3c049e70834cf33790a28643ab058b507b35cBen Chengwhile ($ARGV[0] =~ /^-/) { 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng $_ = shift; 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng last if /^--/; 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (/^-n/) { 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng $nflag++; 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng next; 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng die "I don't recognize this switch: $_\\n"; 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng$printit++ unless $nflag; 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng$\ = "\n"; # automatically add newline on print 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng$n=0; 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng$thumb = 0; # ARM mode by default, not Thumb. 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng@proc_stack = (); 51 52printf (" .syntax unified\n"); 53 54LINE: 55while (<>) { 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. 340if ($nxstack) { 341 printf (" .section\t.note.GNU-stack,\"\",\%\%progbits\n"); 342} 343