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