1221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#!/usr/bin/env perl 2221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 3221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom# PowerPC assembler distiller by <appro>. 4221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 5221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $flavour = shift; 6221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $output = shift; 7221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromopen STDOUT,">$output" || die "can't open $output: $!"; 8221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 9221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy %GLOBALS; 10221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $dotinlocallabels=($flavour=~/linux/)?1:0; 11221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 12221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom################################################################ 13221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom# directives which need special treatment on different platforms 14221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom################################################################ 15221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $globl = sub { 16221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $junk = shift; 17221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $name = shift; 18221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $global = \$GLOBALS{$name}; 19221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $ret; 20221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 21221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $name =~ s|^[\.\_]||; 22221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 23221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom SWITCH: for ($flavour) { 24221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /aix/ && do { $name = ".$name"; 25221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom last; 26221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom }; 27221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /osx/ && do { $name = "_$name"; 28221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom last; 29221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom }; 30221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /linux.*32/ && do { $ret .= ".globl $name\n"; 31221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret .= ".type $name,\@function"; 32221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom last; 33221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom }; 34392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom /linux.*64/ && do { $ret .= ".globl $name\n"; 35392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom $ret .= ".type $name,\@function\n"; 36221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret .= ".section \".opd\",\"aw\"\n"; 37221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret .= ".align 3\n"; 38221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret .= "$name:\n"; 39221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret .= ".quad .$name,.TOC.\@tocbase,0\n"; 40221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret .= ".size $name,24\n"; 41221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret .= ".previous\n"; 42221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 43221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $name = ".$name"; 44221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom last; 45221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom }; 46221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 47221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 48221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret = ".globl $name" if (!$ret); 49221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $$global = $name; 50221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $ret; 51221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 52221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $text = sub { 53221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ($flavour =~ /aix/) ? ".csect" : ".text"; 54221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 55221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $machine = sub { 56221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $junk = shift; 57221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $arch = shift; 58221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if ($flavour =~ /osx/) 59221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { $arch =~ s/\"//g; 60221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $arch = ($flavour=~/64/) ? "ppc970-64" : "ppc970" if ($arch eq "any"); 61221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 62221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ".machine $arch"; 63221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 64392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrommy $size = sub { 65392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom if ($flavour =~ /linux.*32/) 66392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom { shift; 67392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom ".size " . join(",",@_); 68392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 69392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom else 70392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom { ""; } 71392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}; 72221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $asciz = sub { 73221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom shift; 74221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $line = join(",",@_); 75221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if ($line =~ /^"(.*)"$/) 76221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } 77221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 78221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { ""; } 79221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 80221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 81221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom################################################################ 82221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom# simplified mnemonics not handled by at least one assembler 83221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom################################################################ 84221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $cmplw = sub { 85221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $f = shift; 86221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $cr = 0; $cr = shift if ($#_>1); 87221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom # Some out-of-date 32-bit GNU assembler just can't handle cmplw... 88221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ($flavour =~ /linux.*32/) ? 89221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " .long ".sprintf "0x%x",31<<26|$cr<<23|$_[0]<<16|$_[1]<<11|64 : 90221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " cmplw ".join(',',$cr,@_); 91221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 92221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $bdnz = sub { 93221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $f = shift; 94221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $bo = $f=~/[\+\-]/ ? 16+9 : 16; # optional "to be taken" hint 95221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " bc $bo,0,".shift; 96221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom} if ($flavour!~/linux/); 97221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $bltlr = sub { 98221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $f = shift; 99221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $bo = $f=~/\-/ ? 12+2 : 12; # optional "not to be taken" hint 100221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints 101221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " .long ".sprintf "0x%x",19<<26|$bo<<21|16<<1 : 102221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " bclr $bo,0"; 103221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 104221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $bnelr = sub { 105221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $f = shift; 106221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $bo = $f=~/\-/ ? 4+2 : 4; # optional "not to be taken" hint 107221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints 108221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " .long ".sprintf "0x%x",19<<26|$bo<<21|2<<16|16<<1 : 109221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " bclr $bo,2"; 110221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 111221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $beqlr = sub { 112221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $f = shift; 113221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $bo = $f=~/-/ ? 12+2 : 12; # optional "not to be taken" hint 114221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints 115221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " .long ".sprintf "0x%X",19<<26|$bo<<21|2<<16|16<<1 : 116221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " bclr $bo,2"; 117221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 118221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom# GNU assembler can't handle extrdi rA,rS,16,48, or when sum of last two 119221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom# arguments is 64, with "operand out of range" error. 120221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrommy $extrdi = sub { 121221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my ($f,$ra,$rs,$n,$b) = @_; 122221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $b = ($b+$n)&63; $n = 64-$n; 123221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom " rldicl $ra,$rs,$b,$n"; 124221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}; 125221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 126221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromwhile($line=<>) { 127221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 128221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|[#!;].*$||; # get rid of asm-style comments... 129221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|/\*.*\*/||; # ... and C-style comments... 130221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|^\s+||; # ... and skip white spaces in beginning... 131221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|\s+$||; # ... and at the end 132221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 133221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 134221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|\b\.L(\w+)|L$1|g; # common denominator for Locallabel 135221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|\bL(\w+)|\.L$1|g if ($dotinlocallabels); 136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 137221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 138221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 139221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|(^[\.\w]+)\:\s*||; 140221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $label = $1; 141221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom printf "%s:",($GLOBALS{$label} or $label) if ($label); 142221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 143221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 144221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 145221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s*||; 146221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $c = $1; $c = "\t" if ($c eq ""); 147221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $mnemonic = $2; 148221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $f = $3; 149221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom my $opcode = eval("\$$mnemonic"); 150221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom $line =~ s|\bc?[rf]([0-9]+)\b|$1|g if ($c ne "." and $flavour !~ /osx/); 151221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(',',$line)); } 152221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom elsif ($mnemonic) { $line = $c.$mnemonic.$f."\t".$line; } 153221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 154221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 155221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom print $line if ($line); 156221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom print "\n"; 157221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom} 158221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 159221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromclose STDOUT; 160