• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env perl
2
3# ARM assembler distiller by <appro>.
4
5my $flavour = shift;
6my $output = shift;
7open STDOUT,">$output" || die "can't open $output: $!";
8
9$flavour = "linux32" if (!$flavour or $flavour eq "void");
10
11my %GLOBALS;
12my $dotinlocallabels=($flavour=~/linux/)?1:0;
13
14################################################################
15# directives which need special treatment on different platforms
16################################################################
17my $arch = sub {
18    if ($flavour =~ /linux/)	{ ".arch\t".join(',',@_); }
19    else			{ ""; }
20};
21my $fpu = sub {
22    if ($flavour =~ /linux/)	{ ".fpu\t".join(',',@_); }
23    else			{ ""; }
24};
25my $hidden = sub {
26    if ($flavour =~ /ios/)	{ ".private_extern\t".join(',',@_); }
27    else			{ ".hidden\t".join(',',@_); }
28};
29my $comm = sub {
30    my @args = split(/,\s*/,shift);
31    my $name = @args[0];
32    my $global = \$GLOBALS{$name};
33    my $ret;
34
35    if ($flavour =~ /ios32/)	{
36	$ret = ".comm\t_$name,@args[1]\n";
37	$ret .= ".non_lazy_symbol_pointer\n";
38	$ret .= "$name:\n";
39	$ret .= ".indirect_symbol\t_$name\n";
40	$ret .= ".long\t0";
41	$name = "_$name";
42    } else			{ $ret = ".comm\t".join(',',@args); }
43
44    $$global = $name;
45    $ret;
46};
47my $globl = sub {
48    my $name = shift;
49    my $global = \$GLOBALS{$name};
50    my $ret;
51
52    SWITCH: for ($flavour) {
53	/ios/		&& do { $name = "_$name";
54				last;
55			      };
56    }
57
58    $ret = ".globl	$name" if (!$ret);
59    $$global = $name;
60    $ret;
61};
62my $global = $globl;
63my $extern = sub {
64    &$globl(@_);
65    return;	# return nothing
66};
67my $type = sub {
68    if ($flavour =~ /linux/)	{ ".type\t".join(',',@_); }
69    else			{ ""; }
70};
71my $size = sub {
72    if ($flavour =~ /linux/)	{ ".size\t".join(',',@_); }
73    else			{ ""; }
74};
75my $inst = sub {
76    if ($flavour =~ /linux/)    { ".inst\t".join(',',@_); }
77    else                        { ".long\t".join(',',@_); }
78};
79my $asciz = sub {
80    my $line = join(",",@_);
81    if ($line =~ /^"(.*)"$/)
82    {	".byte	" . join(",",unpack("C*",$1),0) . "\n.align	2";	}
83    else
84    {	"";	}
85};
86
87sub range {
88  my ($r,$sfx,$start,$end) = @_;
89
90    join(",",map("$r$_$sfx",($start..$end)));
91}
92
93sub expand_line {
94  my $line = shift;
95  my @ret = ();
96
97    pos($line)=0;
98
99    while ($line =~ m/\G[^@\/\{\"]*/g) {
100	if ($line =~ m/\G(@|\/\/|$)/gc) {
101	    last;
102	}
103	elsif ($line =~ m/\G\{/gc) {
104	    my $saved_pos = pos($line);
105	    $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e;
106	    pos($line) = $saved_pos;
107	    $line =~ m/\G[^\}]*\}/g;
108	}
109	elsif ($line =~ m/\G\"/gc) {
110	    $line =~ m/\G[^\"]*\"/g;
111	}
112    }
113
114    $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge;
115
116    return $line;
117}
118
119print "#if defined(__arm__)\n" if ($flavour eq "linux32");
120print "#if defined(__aarch64__)\n" if ($flavour eq "linux64");
121
122while($line=<>) {
123
124    if ($line =~ m/^\s*(#|@|\/\/)/)	{ print $line; next; }
125
126    $line =~ s|/\*.*\*/||;	# get rid of C-style comments...
127    $line =~ s|^\s+||;		# ... and skip white spaces in beginning...
128    $line =~ s|\s+$||;		# ... and at the end
129
130    {
131	$line =~ s|[\b\.]L(\w{2,})|L$1|g;	# common denominator for Locallabel
132	$line =~ s|\bL(\w{2,})|\.L$1|g	if ($dotinlocallabels);
133    }
134
135    {
136	$line =~ s|(^[\.\w]+)\:\s*||;
137	my $label = $1;
138	if ($label) {
139	    printf "%s:",($GLOBALS{$label} or $label);
140	}
141    }
142
143    if ($line !~ m/^[#@]/) {
144	$line =~ s|^\s*(\.?)(\S+)\s*||;
145	my $c = $1; $c = "\t" if ($c eq "");
146	my $mnemonic = $2;
147	my $opcode;
148	if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) {
149	    $opcode = eval("\$$1_$2");
150	} else {
151	    $opcode = eval("\$$mnemonic");
152	}
153
154	my $arg=expand_line($line);
155
156	if (ref($opcode) eq 'CODE') {
157		$line = &$opcode($arg);
158	} elsif ($mnemonic)         {
159		$line = $c.$mnemonic;
160		$line.= "\t$arg" if ($arg ne "");
161	}
162    }
163
164    print $line if ($line);
165    print "\n";
166}
167
168print "#endif" if ($flavour eq "linux32" || $flavour eq "linux64");
169
170close STDOUT;
171