1238384Sjkim#!/usr/bin/env perl 2238384Sjkim 3238384Sjkim# PowerPC assembler distiller by <appro>. 4238384Sjkim 5238384Sjkimmy $flavour = shift; 6238384Sjkimmy $output = shift; 7238384Sjkimopen STDOUT,">$output" || die "can't open $output: $!"; 8238384Sjkim 9238384Sjkimmy %GLOBALS; 10238384Sjkimmy $dotinlocallabels=($flavour=~/linux/)?1:0; 11238384Sjkim 12238384Sjkim################################################################ 13238384Sjkim# directives which need special treatment on different platforms 14238384Sjkim################################################################ 15238384Sjkimmy $globl = sub { 16238384Sjkim my $junk = shift; 17238384Sjkim my $name = shift; 18238384Sjkim my $global = \$GLOBALS{$name}; 19238384Sjkim my $ret; 20238384Sjkim 21238384Sjkim $name =~ s|^[\.\_]||; 22238384Sjkim 23238384Sjkim SWITCH: for ($flavour) { 24238384Sjkim /aix/ && do { $name = ".$name"; 25238384Sjkim last; 26238384Sjkim }; 27238384Sjkim /osx/ && do { $name = "_$name"; 28238384Sjkim last; 29238384Sjkim }; 30238384Sjkim /linux.*32/ && do { $ret .= ".globl $name\n"; 31238384Sjkim $ret .= ".type $name,\@function"; 32238384Sjkim last; 33238384Sjkim }; 34238384Sjkim /linux.*64/ && do { $ret .= ".globl $name\n"; 35238384Sjkim $ret .= ".type $name,\@function\n"; 36238384Sjkim $ret .= ".section \".opd\",\"aw\"\n"; 37238384Sjkim $ret .= ".align 3\n"; 38238384Sjkim $ret .= "$name:\n"; 39238384Sjkim $ret .= ".quad .$name,.TOC.\@tocbase,0\n"; 40238384Sjkim $ret .= ".size $name,24\n"; 41238384Sjkim $ret .= ".previous\n"; 42238384Sjkim 43238384Sjkim $name = ".$name"; 44238384Sjkim last; 45238384Sjkim }; 46238384Sjkim } 47238384Sjkim 48238384Sjkim $ret = ".globl $name" if (!$ret); 49238384Sjkim $$global = $name; 50238384Sjkim $ret; 51238384Sjkim}; 52238384Sjkimmy $text = sub { 53238384Sjkim ($flavour =~ /aix/) ? ".csect" : ".text"; 54238384Sjkim}; 55238384Sjkimmy $machine = sub { 56238384Sjkim my $junk = shift; 57238384Sjkim my $arch = shift; 58238384Sjkim if ($flavour =~ /osx/) 59238384Sjkim { $arch =~ s/\"//g; 60238384Sjkim $arch = ($flavour=~/64/) ? "ppc970-64" : "ppc970" if ($arch eq "any"); 61238384Sjkim } 62238384Sjkim ".machine $arch"; 63238384Sjkim}; 64238384Sjkimmy $size = sub { 65238384Sjkim if ($flavour =~ /linux.*32/) 66238384Sjkim { shift; 67238384Sjkim ".size " . join(",",@_); 68238384Sjkim } 69238384Sjkim else 70238384Sjkim { ""; } 71238384Sjkim}; 72238384Sjkimmy $asciz = sub { 73238384Sjkim shift; 74238384Sjkim my $line = join(",",@_); 75238384Sjkim if ($line =~ /^"(.*)"$/) 76238384Sjkim { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } 77238384Sjkim else 78238384Sjkim { ""; } 79238384Sjkim}; 80238384Sjkim 81238384Sjkim################################################################ 82238384Sjkim# simplified mnemonics not handled by at least one assembler 83238384Sjkim################################################################ 84238384Sjkimmy $cmplw = sub { 85238384Sjkim my $f = shift; 86238384Sjkim my $cr = 0; $cr = shift if ($#_>1); 87238384Sjkim # Some out-of-date 32-bit GNU assembler just can't handle cmplw... 88238384Sjkim ($flavour =~ /linux.*32/) ? 89238384Sjkim " .long ".sprintf "0x%x",31<<26|$cr<<23|$_[0]<<16|$_[1]<<11|64 : 90238384Sjkim " cmplw ".join(',',$cr,@_); 91238384Sjkim}; 92238384Sjkimmy $bdnz = sub { 93238384Sjkim my $f = shift; 94238384Sjkim my $bo = $f=~/[\+\-]/ ? 16+9 : 16; # optional "to be taken" hint 95238384Sjkim " bc $bo,0,".shift; 96238384Sjkim} if ($flavour!~/linux/); 97238384Sjkimmy $bltlr = sub { 98238384Sjkim my $f = shift; 99238384Sjkim my $bo = $f=~/\-/ ? 12+2 : 12; # optional "not to be taken" hint 100238384Sjkim ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints 101238384Sjkim " .long ".sprintf "0x%x",19<<26|$bo<<21|16<<1 : 102238384Sjkim " bclr $bo,0"; 103238384Sjkim}; 104238384Sjkimmy $bnelr = sub { 105238384Sjkim my $f = shift; 106238384Sjkim my $bo = $f=~/\-/ ? 4+2 : 4; # optional "not to be taken" hint 107238384Sjkim ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints 108238384Sjkim " .long ".sprintf "0x%x",19<<26|$bo<<21|2<<16|16<<1 : 109238384Sjkim " bclr $bo,2"; 110238384Sjkim}; 111238384Sjkimmy $beqlr = sub { 112238384Sjkim my $f = shift; 113238384Sjkim my $bo = $f=~/-/ ? 12+2 : 12; # optional "not to be taken" hint 114238384Sjkim ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints 115238384Sjkim " .long ".sprintf "0x%X",19<<26|$bo<<21|2<<16|16<<1 : 116238384Sjkim " bclr $bo,2"; 117238384Sjkim}; 118238384Sjkim# GNU assembler can't handle extrdi rA,rS,16,48, or when sum of last two 119238384Sjkim# arguments is 64, with "operand out of range" error. 120238384Sjkimmy $extrdi = sub { 121238384Sjkim my ($f,$ra,$rs,$n,$b) = @_; 122238384Sjkim $b = ($b+$n)&63; $n = 64-$n; 123238384Sjkim " rldicl $ra,$rs,$b,$n"; 124238384Sjkim}; 125238384Sjkim 126238384Sjkimwhile($line=<>) { 127238384Sjkim 128238384Sjkim $line =~ s|[#!;].*$||; # get rid of asm-style comments... 129238384Sjkim $line =~ s|/\*.*\*/||; # ... and C-style comments... 130238384Sjkim $line =~ s|^\s+||; # ... and skip white spaces in beginning... 131238384Sjkim $line =~ s|\s+$||; # ... and at the end 132238384Sjkim 133238384Sjkim { 134238384Sjkim $line =~ s|\b\.L(\w+)|L$1|g; # common denominator for Locallabel 135238384Sjkim $line =~ s|\bL(\w+)|\.L$1|g if ($dotinlocallabels); 136238384Sjkim } 137238384Sjkim 138238384Sjkim { 139238384Sjkim $line =~ s|(^[\.\w]+)\:\s*||; 140238384Sjkim my $label = $1; 141238384Sjkim printf "%s:",($GLOBALS{$label} or $label) if ($label); 142238384Sjkim } 143238384Sjkim 144238384Sjkim { 145238384Sjkim $line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s*||; 146238384Sjkim my $c = $1; $c = "\t" if ($c eq ""); 147238384Sjkim my $mnemonic = $2; 148238384Sjkim my $f = $3; 149238384Sjkim my $opcode = eval("\$$mnemonic"); 150238384Sjkim $line =~ s|\bc?[rf]([0-9]+)\b|$1|g if ($c ne "." and $flavour !~ /osx/); 151238384Sjkim if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(',',$line)); } 152238384Sjkim elsif ($mnemonic) { $line = $c.$mnemonic.$f."\t".$line; } 153238384Sjkim } 154238384Sjkim 155238384Sjkim print $line if ($line); 156238384Sjkim print "\n"; 157238384Sjkim} 158238384Sjkim 159238384Sjkimclose STDOUT; 160