sbsv1/abld/e32util/armasm2as.pl
changeset 599 fa7a3cc6effd
child 626 ac03b93ca9c4
equal deleted inserted replaced
596:9f25be3da657 599:fa7a3cc6effd
       
     1 # Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # All rights reserved.
       
     3 # This component and the accompanying materials are made available
       
     4 # under the terms of "Eclipse Public License v1.0"
       
     5 # which accompanies this distribution, and is available
       
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 #
       
     8 # Initial Contributors:
       
     9 # Nokia Corporation - initial contribution.
       
    10 #
       
    11 # Contributors:
       
    12 #
       
    13 # Description:
       
    14 # e32toolp\e32util\armasm2as.pl
       
    15 # Convert an ARMASM assembler source or include file to AS format
       
    16 # Syntax:
       
    17 # perl armasm2as.pl <input> <output>
       
    18 # 
       
    19 #
       
    20 
       
    21 if (scalar(@ARGV)!=2) {
       
    22 	die "perl armasm2as.pl <input> <output>\n";
       
    23 }
       
    24 my ($infile, $outfile) = @ARGV;
       
    25 open IN, $infile or die "Can't open $infile for input\n";
       
    26 my $gccfile;
       
    27 my @input;
       
    28 while (<IN>) {
       
    29 	push @input, $_;
       
    30 	next if defined($gccfile);
       
    31 	next if (/^\s*$/);
       
    32 	if (/^\s*\@/) {
       
    33 		$gccfile = 1;	# If first non-blank line starts with @, assume already in GCC format
       
    34 	} else {
       
    35 		$gccfile = 0;
       
    36 	}
       
    37 }
       
    38 close IN;
       
    39 my @output;
       
    40 my $outref = \@output;
       
    41 if ($gccfile) {
       
    42 	$outref = \@input;
       
    43 } else {
       
    44 	process(\@input, \@output);
       
    45 }
       
    46 open OUT, ">$outfile" or die "Can't open $outfile for write\n";
       
    47 print OUT @$outref;
       
    48 close OUT;
       
    49 
       
    50 
       
    51 
       
    52 sub process($$) {
       
    53 	my $level=0;
       
    54 	my @block;
       
    55 	my ($inref, $outref) = @_;
       
    56 	foreach $line (@$inref) {
       
    57 		$line=~s/\s*$//;
       
    58 		my $comment;
       
    59 		if ($line =~ /\;(.*)$/o) {
       
    60 			$comment = $1;
       
    61 			$line =~ s/\;(.*)$//o;
       
    62 			if ($line =~ /^\s*$/o and $level==0) {
       
    63 				push @$outref, "$line\@$comment\n";
       
    64 				next;
       
    65 			}
       
    66 			$comment = "\t\@$comment";
       
    67 		}
       
    68 		if ($line =~ /^\s+PRESERVE8/) {
       
    69 			next;
       
    70 		}
       
    71 		if ($level == 1) {
       
    72 			if ($line =~ /^\s+MEND/i) {
       
    73 				process_macro(\@block, $outref);
       
    74 				$level = 0;
       
    75 			} else {
       
    76 				push @block, $line;
       
    77 			}
       
    78 			next;
       
    79 		} elsif ($level == 0) {
       
    80 			if ($line =~ /^\s+MACRO\s*$/i) {
       
    81 				@block = ();
       
    82 				$level = 1;
       
    83 				next;
       
    84 			}
       
    85 		}
       
    86 		if ($line =~ /^\s+GBLL\s+(\S+)/i) {
       
    87 			push @$outref, "\t.set\t$1, 0$comment\n";
       
    88 			next;
       
    89 		}
       
    90 		if ($line =~ /^\s+GBLA\s+(\S+)/i) {
       
    91 			push @$outref, "\t.set\t$1, 0$comment\n";
       
    92 			next;
       
    93 		}
       
    94 		if ($line =~ /^\s+INCLUDE\s+(\S+)/i) {
       
    95 			my $arg = $1;
       
    96 			if ($arg =~ /(\w+)\.inc/io) {
       
    97 				$arg = $1.'.ginc';
       
    98 			}
       
    99 			push @$outref, "\t.include\t\"$arg\"$comment\n";
       
   100 			next;
       
   101 		}
       
   102 		if ($line =~ /^\s+IMPORT\s+(\S+)/i) {
       
   103 			push @$outref, "\t.extern\t$1$comment\n";
       
   104 			next;
       
   105 		}
       
   106 		if ($line =~ /^\s+EXPORT\s+(\S+)/i) {
       
   107 			push @$outref, "\t.global\t$1$comment\n";
       
   108 			next;
       
   109 		}
       
   110 		if ($line =~ /^\s+ELSE/i or $line =~ /^\s+\|/i ) {
       
   111 			push @$outref, "\t.else$comment\n";
       
   112 			next;
       
   113 		}
       
   114 		if ($line =~ /^\s+ENDIF/i or $line =~ /^\s+\]/i) {
       
   115 			push @$outref, "\t.endif$comment\n";
       
   116 			next;
       
   117 		}
       
   118 		if ($line =~ /^\s+LTORG/i) {
       
   119 			push @$outref, "\t.ltorg$comment\n";
       
   120 			next;
       
   121 		}
       
   122 		if ($line =~ /^\s+END$/i) {
       
   123 			next;
       
   124 		}
       
   125 		if ($line =~ /^\s+\!\s*(\d+)\,\s*(.*?)$/) {
       
   126 			my $msg = $2;
       
   127 			push @$outref, "\t.print $msg\n\t.err$comment\n";
       
   128 			next;
       
   129 		}
       
   130 		if ($line =~ /^\s+INIT_LOGICAL_SYMBOL\s+(\w+)(.*?)$/) {
       
   131 			process_init_logical_symbol($1, $2, $outref, $comment);
       
   132 			next;
       
   133 		}
       
   134 		if ($line =~ /^\s+INIT_NUMERIC_SYMBOL\s+(\w+)\s*\,\s*(.*?)$/) {
       
   135 			process_init_numeric_symbol($1, $2, $outref, $comment);
       
   136 			next;
       
   137 		}
       
   138 		if ($line =~ /^\s+AREA\s+(.*?)$/) {
       
   139 			process_area($1, $outref, $comment);
       
   140 			next;
       
   141 		}
       
   142 		if ($line =~ /^\s+\%\s+(.*?)$/) {
       
   143 			my $expr = process_numeric_expr($1, $outref);
       
   144 			push @$outref, "\t.space $expr$comment\n";
       
   145 			next;
       
   146 		}
       
   147 		if ($line =~ /^\s+ALIGN\s*(.*?)$/) {
       
   148 			process_align($1, $outref, $comment);
       
   149 			next;
       
   150 		}
       
   151 
       
   152 		# Strip label if there is one
       
   153 		my $label;
       
   154 		if ($line =~ /^(\S+)\s*(.*?)$/) {
       
   155 			$label = $1;
       
   156 			$line = $2;
       
   157 		} else {
       
   158 			$line =~ s/^\s*//;
       
   159 		}
       
   160 		if ($line =~ /^SETL\s+(\S+)/i) {
       
   161 			my $val = $1;
       
   162 			my $expr = process_logical_expr($val, $outref);
       
   163 			push @$outref, "\t.set\t$label,$expr$comment\n";
       
   164 			next;
       
   165 		}
       
   166 		if ($line =~ /^SETA\s+(.*?)$/i) {
       
   167 			my $val = $1;
       
   168 			my $expr = process_numeric_expr($val, $outref);
       
   169 			push @$outref, "\t.set\t$label,$expr$comment\n";
       
   170 			next;
       
   171 		}
       
   172 		if ($line =~ /^(EQU|\*)\s+(.*?)$/i) {
       
   173 			my $val = $2;
       
   174 			my $expr = process_numeric_expr($val, $outref);
       
   175 			push @$outref, "\t.equ\t$label,$expr$comment\n";
       
   176 			next;
       
   177 		}
       
   178 		if ($line =~ /^(if|\[)\s+(.*?)$/i) {
       
   179 			my $cond = $2;
       
   180 			if ($cond =~ /^\s*(\:LNOT\:)?\s*\:DEF\:\s*(.*?)$/i) {
       
   181 				my $n = $1;
       
   182 				my $sym = $2;
       
   183 				if ($sym =~ /^(\w|\\|\:)+$/) {
       
   184 					if (uc($n) eq ':LNOT:') {
       
   185 						push @$outref, "\t.ifndef\t$sym$comment\n";
       
   186 					} else {
       
   187 						push @$outref, "\t.ifdef\t$sym$comment\n";
       
   188 					}
       
   189 					next;
       
   190 				}
       
   191 			}
       
   192 			my $expr = process_logical_expr($cond, $outref);
       
   193 			push @$outref, "\t.if $expr$comment\n";
       
   194 			next;
       
   195 		}
       
   196 		if ($line =~ /^(\=|DCB)\s*(.*?)$/) {
       
   197 			process_dcb($label, $2, $outref, $comment);
       
   198 			next;
       
   199 		}
       
   200 		if ($line =~ /^DCW\s*(.*?)$/) {
       
   201 			process_dcw($label, $1, $outref, $comment);
       
   202 			next;
       
   203 		}
       
   204 		if ($line =~ /^DCD\s*(.*?)$/) {
       
   205 			process_dcd($label, $1, $outref, $comment);
       
   206 			next;
       
   207 		}
       
   208 		if ($line =~ /^ROUT\s*$/) {
       
   209 			$line = '';
       
   210 		}
       
   211 		if ($line =~ /^(\w+)\s+\%(\w+)\s*$/o) {
       
   212 			# ARMASM local label reference
       
   213 			my $inst = $1;
       
   214 			my $llab = $2;
       
   215 			if ($llab =~ /F\w?(\d+)/o) {
       
   216 				$line = "$inst $1f";
       
   217 			} elsif ($llab =~ /B\w?(\d+)/o) {
       
   218 				$line = "$inst $1b";
       
   219 			} else {
       
   220 				die "Can't determine local label direction\n";
       
   221 			}
       
   222 		}
       
   223 		if ($line =~ /^(\w+)\s+(\w+)\s*\,\s*\%(\w+)\s*$/o) {
       
   224 			# ARMASM local label reference
       
   225 			my $inst = $1;
       
   226 			my $op1 = $2;
       
   227 			my $llab = $3;
       
   228 			if ($llab =~ /F\w?(\d+)/o) {
       
   229 				$line = "$inst $op1\, $1f";
       
   230 			} elsif ($llab =~ /B\w?(\d+)/o) {
       
   231 				$line = "$inst $op1\, $1b";
       
   232 			} else {
       
   233 				die "Can't determine local label direction\n";
       
   234 			}
       
   235 		}
       
   236 
       
   237 		$line = process_numeric_expr($line, $outref);
       
   238 		if (defined($label)) {
       
   239 			push @$outref, "$label\:\t$line$comment\n";
       
   240 		} else {
       
   241 			push @$outref, "\t$line$comment\n";
       
   242 		}
       
   243 	}
       
   244 }
       
   245 
       
   246 
       
   247 sub process_macro($$) {
       
   248 	my ($inref, $outref) = @_;
       
   249 	my $line;
       
   250 	while(1) {
       
   251 		$line = shift @$inref;
       
   252 		last if ($line !~ /^\s*$/);
       
   253 	}
       
   254 	unless ($line =~ /^\s+(\w+)\s*(.*?)$/) {
       
   255 		die "Bad macro - no name\n";
       
   256 	}
       
   257 	my $macro_name = $1;
       
   258 	if ($macro_name eq 'INIT_LOGICAL_SYMBOL' or $macro_name eq 'INIT_NUMERIC_SYMBOL') {
       
   259 		return;
       
   260 	}
       
   261 	$line = $2;
       
   262 	my @args = split ( '\s*,\s*', $line );
       
   263 	foreach (@args) {
       
   264 		die "Bad macro argument name\n" unless (/^\$\w+$/);
       
   265 		s/^\$//;
       
   266 	}
       
   267 	my $ev = '';
       
   268 	foreach $arg (@args) {
       
   269 		$ev.="s/\\\$$arg(\\W\|\$)/\\\\$arg\$1/go;";
       
   270 	}
       
   271 	foreach (@$inref) {
       
   272 		eval $ev;
       
   273 	}
       
   274 	push @$outref, "\t.macro $macro_name ".join(',',@args)."\n";
       
   275 	process($inref, $outref);
       
   276 	push @$outref, "\t.endm\n";
       
   277 }
       
   278 
       
   279 
       
   280 sub process_logical_expr($$) {
       
   281 	my ($val, $outref) = @_;
       
   282 	$val = process_numeric_expr($val, $outref);
       
   283 	$val =~ s/\<\=/________LE________/g;	# protect <= and >= during expansion of =
       
   284 	$val =~ s/\>\=/________GE________/g;
       
   285 	$val =~ s/\=/\=\=/g;					# equality operator is = on ARMASM, == on AS
       
   286 	$val =~ s/________LE________/\<\=/g;
       
   287 	$val =~ s/________GE________/\>\=/g;
       
   288 	$val =~ s/\{TRUE\}/(1)/g;
       
   289 	$val =~ s/\{FALSE\}/(0)/g;
       
   290 
       
   291 	my @lops = split( /(\s*\:LAND\:\s*|\s*\:LOR\:\s*|\s*\:LNOT\:\s*|\s*\:DEF\:\s*)/, $val );
       
   292 	foreach (@lops) {
       
   293 		s/\s*\:LAND\:\s*/\:LAND\:/go;
       
   294 		s/\s*\:LOR\:\s*/\:LOR\:/go;
       
   295 		s/\s*\:LNOT\:\s*/\:LNOT\:/go;
       
   296 		s/\s*\:DEF\:\s*/\:DEF\:/go;
       
   297 	}
       
   298 	my @lops2;
       
   299 	while (scalar (@lops)) {
       
   300 		my $x = shift @lops;
       
   301 		if ($x eq ':DEF:') {
       
   302 			my $sym = shift @lops;
       
   303 			$sym =~ s/^\s*//;
       
   304 			$sym =~ s/\s*$//;
       
   305 			if ($sym =~ /^(\w|\$|\\)+$/) {
       
   306 				push @$outref, "\t.ifdef $sym\n\t.set __defined__$sym, 1\n\t.else\n\t.set __defined__$sym, 0\n\t.endif\n";
       
   307 				push @lops2, " __defined__$sym ";
       
   308 			} else {
       
   309 				die "Bad :DEF: operand\n";
       
   310 			}
       
   311 		} elsif ($x eq ':LAND:') {
       
   312 			push @lops2, ' && ';
       
   313 		} elsif ($x eq ':LOR:') {
       
   314 			push @lops2, ' || ';
       
   315 		} else {
       
   316 			push @lops2, $x;
       
   317 		}
       
   318 	}
       
   319 	my @lops3;
       
   320 	while (scalar (@lops2)) {
       
   321 		my $x = shift @lops2;
       
   322 		if ($x eq ':LNOT:') {
       
   323 			my $operand;
       
   324 			while (1) {
       
   325 				$operand = shift @lops2;
       
   326 				last if ($operand !~ /^\s*$/);
       
   327 			}
       
   328 			push @lops3, "(0==($operand))";
       
   329 		} else {
       
   330 			push @lops3, $x;
       
   331 		}
       
   332 	}
       
   333 	return join('',@lops3);
       
   334 }
       
   335 
       
   336 sub process_numeric_expr($$) {
       
   337 	my ($val, $outref) = @_;
       
   338 	$val =~ s/\&/0x/g;			# ARMASM accepts hex numbers starting with & or 0x, AS only accepts 0x
       
   339 	$val =~ s/(\W|^)2_([0|1]+)(\W|$)/$1 0b$2$3/g;	# Binary numbers start with 2_ on ARMASM, 0b on AS
       
   340 	$val =~ s/\:AND\:/\&/g;
       
   341 	$val =~ s/\:OR\:/\|/g;
       
   342 	$val =~ s/\:SHL\:/\<\</g;
       
   343 	$val =~ s/\:SHR\:/\>\>/g;
       
   344 	return $val;
       
   345 }
       
   346 
       
   347 sub process_init_logical_symbol($$$$) {
       
   348 	my ($name, $rest, $outref, $comment) = @_;
       
   349 	my $counter;
       
   350 	if ($rest =~ /^\s*\,\s*(\w+)\s*$/) {
       
   351 		$counter = $1;
       
   352 	} elsif ($rest !~ /^\s*$/) {
       
   353 		die "Bad INIT_LOGICAL_SYMBOL\n";
       
   354 	}
       
   355 	push @$outref, "\t.ifndef $name$comment\n\t.set $name, 0\n\t.else\n\t.set $name, 1\n";
       
   356 	if ($counter) {
       
   357 		push @$outref, "\t.set $counter, $counter \+ 1\n";
       
   358 	}
       
   359 	push @$outref, "\t.endif\n";
       
   360 }
       
   361 
       
   362 sub process_init_numeric_symbol($$$$) {
       
   363 	my ($name, $value, $outref, $comment) = @_;
       
   364 	my $expr = process_numeric_expr($value, $outref);
       
   365 	push @$outref, "\t.ifndef $name$comment\n\t.set $name, $expr\n\t.endif\n";
       
   366 }
       
   367 
       
   368 sub process_area($$$) {
       
   369 	my ($line, $outref, $comment) = @_;
       
   370 	my @args = split(',',$line);
       
   371 	my $align = 0;
       
   372 	foreach (@args) {
       
   373 		if (/^\s*ALIGN\s*\=\s*(\d+)\s*$/) {
       
   374 			$align = $1;
       
   375 		}
       
   376 	}
       
   377 	push @$outref, "\t.text$comment\n\t.p2align $align\n";
       
   378 }
       
   379 
       
   380 sub process_align($$$) {
       
   381 	my ($line, $outref, $comment) = @_;
       
   382 	if ($line =~ /^\s*$/o) {
       
   383 		push @$outref, "\t.align$comment\n";
       
   384 	} else {
       
   385 		push @$outref, "\t.balign $line$comment\n";
       
   386 	}
       
   387 }
       
   388 
       
   389 sub process_dcb($$$$) {
       
   390 	my ($label, $args, $outref, $comment) = @_;
       
   391 	if (defined($label)) {
       
   392 		push @$outref, "$label\:";
       
   393 	}
       
   394 	while ($args !~ /^\s*$/) {
       
   395 		my $arg;
       
   396 		$args =~ s/^\s*//;
       
   397 		if ($args =~ /^\"/) {
       
   398 			$args =~ s/\\\"/________ESCAPED_QUOTE________/go;
       
   399 			$args =~ /\"(.*?)\"\s*(.*?)$/o or die "Unterminated string literal\n";
       
   400 			$arg = $1;
       
   401 			$args = $2;
       
   402 			$arg =~ s/________ESCAPED_QUOTE________/\\\"/go;
       
   403 			push @$outref, "\t.ascii \"$arg\"$comment\n";
       
   404 			undef $comment;
       
   405 			last if ($args !~ /\s*\,(.*?)$/o);
       
   406 			$args = $1;
       
   407 		} else {
       
   408 			$args =~ /(.*?)\s*(\,|$)(.*?)$/o;
       
   409 			$arg = $1;
       
   410 			$args = $3;
       
   411 			my $expr = process_numeric_expr($arg, $outref);
       
   412 			push @$outref, "\t.byte $expr$comment\n";
       
   413 			undef $comment;
       
   414 		}
       
   415 	}
       
   416 }
       
   417 
       
   418 sub process_dcw($$$$) {
       
   419 	my ($label, $args, $outref, $comment) = @_;
       
   420 	if (defined($label)) {
       
   421 		push @$outref, "$label\:";
       
   422 	}
       
   423 	while ($args !~ /^\s*$/) {
       
   424 		my $arg;
       
   425 		$args =~ s/^\s*//;
       
   426 		$args =~ /(.*?)\s*(\,|$)(.*?)$/o;
       
   427 		$arg = $1;
       
   428 		$args = $3;
       
   429 		my $expr = process_numeric_expr($arg, $outref);
       
   430 		push @$outref, "\t.hword $expr$comment\n";
       
   431 		undef $comment;
       
   432 	}
       
   433 }
       
   434 
       
   435 sub process_dcd($$$$) {
       
   436 	my ($label, $args, $outref, $comment) = @_;
       
   437 	if (defined($label)) {
       
   438 		push @$outref, "$label\:";
       
   439 	}
       
   440 	while ($args !~ /^\s*$/) {
       
   441 		my $arg;
       
   442 		$args =~ s/^\s*//;
       
   443 		$args =~ /(.*?)\s*(\,|$)(.*?)$/o;
       
   444 		$arg = $1;
       
   445 		$args = $3;
       
   446 		my $expr = process_numeric_expr($arg, $outref);
       
   447 		push @$outref, "\t.word $expr$comment\n";
       
   448 		undef $comment;
       
   449 	}
       
   450 }
       
   451 
       
   452 
       
   453