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