1 #!/usr/bin/env perl 2 # SPDX-License-Identifier: GPL-2.0 3 4 # PowerPC assembler distiller by <appro>. 5 6 my $flavour = shift; 7 my $output = shift; 8 open STDOUT,">$output" || die "can't open $out 9 10 my %GLOBALS; 11 my $dotinlocallabels=($flavour=~/linux/)?1:0; 12 13 ############################################## 14 # directives which need special treatment on d 15 ############################################## 16 my $globl = sub { 17 my $junk = shift; 18 my $name = shift; 19 my $global = \$GLOBALS{$name}; 20 my $ret; 21 22 $name =~ s|^[\.\_]||; 23 24 SWITCH: for ($flavour) { 25 /aix/ && do { $name = ".$nam 26 last; 27 }; 28 /osx/ && do { $name = "_$nam 29 last; 30 }; 31 /linux/ 32 && do { $ret = "_GLOBA 33 last; 34 }; 35 } 36 37 $ret = ".globl $name\nalign 5\n$name: 38 $$global = $name; 39 $ret; 40 }; 41 my $text = sub { 42 my $ret = ($flavour =~ /aix/) ? ".csect\t. 43 $ret = ".abiversion 2\n".$ret if ($f 44 $ret; 45 }; 46 my $machine = sub { 47 my $junk = shift; 48 my $arch = shift; 49 if ($flavour =~ /osx/) 50 { $arch =~ s/\"//g; 51 $arch = ($flavour=~/64/) ? "ppc970-64" 52 } 53 ".machine $arch"; 54 }; 55 my $size = sub { 56 if ($flavour =~ /linux/) 57 { shift; 58 my $name = shift; $name =~ s|^[\.\_]|| 59 my $ret = ".size $name,.-".($fl 60 $ret .= "\n.size .$name,.-.$nam 61 $ret; 62 } 63 else 64 { ""; } 65 }; 66 my $asciz = sub { 67 shift; 68 my $line = join(",",@_); 69 if ($line =~ /^"(.*)"$/) 70 { ".byte " . join(",",unpack("C*",$1),0 71 else 72 { ""; } 73 }; 74 my $quad = sub { 75 shift; 76 my @ret; 77 my ($hi,$lo); 78 for (@_) { 79 if (/^0x([0-9a-f]*?)([0-9a-f]{1,8})$/i 80 { $hi=$1?"0x$1":"0"; $lo="0x$2"; } 81 elsif (/^([0-9]+)$/o) 82 { $hi=$1>>32; $lo=$1&0xffffffff; } # 83 else 84 { $hi=undef; $lo=$_; } 85 86 if (defined($hi)) 87 { push(@ret,$flavour=~/le$/o?".long\t 88 else 89 { push(@ret,".quad $lo"); } 90 } 91 join("\n",@ret); 92 }; 93 94 ############################################## 95 # simplified mnemonics not handled by at least 96 ############################################## 97 my $cmplw = sub { 98 my $f = shift; 99 my $cr = 0; $cr = shift if ($#_>1); 100 # Some out-of-date 32-bit GNU assembler ju 101 ($flavour =~ /linux.*32/) ? 102 " .long ".sprintf "0x%x",31<<2 103 " cmplw ".join(',',$cr,@_); 104 }; 105 my $bdnz = sub { 106 my $f = shift; 107 my $bo = $f=~/[\+\-]/ ? 16+9 : 16; # opti 108 " bc $bo,0,".shift; 109 } if ($flavour!~/linux/); 110 my $bltlr = sub { 111 my $f = shift; 112 my $bo = $f=~/\-/ ? 12+2 : 12; # opti 113 ($flavour =~ /linux/) ? # GNU 114 " .long ".sprintf "0x%x",19<<2 115 " bclr $bo,0"; 116 }; 117 my $bnelr = sub { 118 my $f = shift; 119 my $bo = $f=~/\-/ ? 4+2 : 4; # opti 120 ($flavour =~ /linux/) ? # GNU 121 " .long ".sprintf "0x%x",19<<2 122 " bclr $bo,2"; 123 }; 124 my $beqlr = sub { 125 my $f = shift; 126 my $bo = $f=~/-/ ? 12+2 : 12; # opti 127 ($flavour =~ /linux/) ? # GNU 128 " .long ".sprintf "0x%X",19<<2 129 " bclr $bo,2"; 130 }; 131 # GNU assembler can't handle extrdi rA,rS,16,4 132 # arguments is 64, with "operand out of range" 133 my $extrdi = sub { 134 my ($f,$ra,$rs,$n,$b) = @_; 135 $b = ($b+$n)&63; $n = 64-$n; 136 " rldicl $ra,$rs,$b,$n"; 137 }; 138 my $vmr = sub { 139 my ($f,$vx,$vy) = @_; 140 " vor $vx,$vy,$vy"; 141 }; 142 143 # Some ABIs specify vrsave, special-purpose re 144 # for system use. 145 my $no_vrsave = ($flavour =~ /linux-ppc64le/); 146 my $mtspr = sub { 147 my ($f,$idx,$ra) = @_; 148 if ($idx == 256 && $no_vrsave) { 149 " or $ra,$ra,$ra"; 150 } else { 151 " mtspr $idx,$ra"; 152 } 153 }; 154 my $mfspr = sub { 155 my ($f,$rd,$idx) = @_; 156 if ($idx == 256 && $no_vrsave) { 157 " li $rd,-1"; 158 } else { 159 " mfspr $rd,$idx"; 160 } 161 }; 162 163 # PowerISA 2.06 stuff 164 sub vsxmem_op { 165 my ($f, $vrt, $ra, $rb, $op) = @_; 166 " .long ".sprintf "0x%X",(31<<26)|($vr 167 } 168 # made-up unaligned memory reference AltiVec/V 169 my $lvx_u = sub { vsxmem_op(@_, 844); }; 170 my $stvx_u = sub { vsxmem_op(@_, 972); }; 171 my $lvdx_u = sub { vsxmem_op(@_, 588); }; 172 my $stvdx_u = sub { vsxmem_op(@_, 716); }; 173 my $lvx_4w = sub { vsxmem_op(@_, 780); }; 174 my $stvx_4w = sub { vsxmem_op(@_, 908); }; 175 176 # PowerISA 2.07 stuff 177 sub vcrypto_op { 178 my ($f, $vrt, $vra, $vrb, $op) = @_; 179 " .long ".sprintf "0x%X",(4<<26)|($vrt 180 } 181 my $vcipher = sub { vcrypto_op(@_, 1288); 182 my $vcipherlast = sub { vcrypto_op(@_, 1289); 183 my $vncipher = sub { vcrypto_op(@_, 1352); 184 my $vncipherlast= sub { vcrypto_op(@_, 1353); 185 my $vsbox = sub { vcrypto_op(@_, 0, 1480 186 my $vshasigmad = sub { my ($st,$six)=splice(@ 187 my $vshasigmaw = sub { my ($st,$six)=splice(@ 188 my $vpmsumb = sub { vcrypto_op(@_, 1032); 189 my $vpmsumd = sub { vcrypto_op(@_, 1224); 190 my $vpmsubh = sub { vcrypto_op(@_, 1096); 191 my $vpmsumw = sub { vcrypto_op(@_, 1160); 192 my $vaddudm = sub { vcrypto_op(@_, 192); 193 my $vadduqm = sub { vcrypto_op(@_, 256); 194 195 my $mtsle = sub { 196 my ($f, $arg) = @_; 197 " .long ".sprintf "0x%X",(31<<26)|($ar 198 }; 199 200 print "#include <asm/ppc_asm.h>\n" if $flavour 201 202 while($line=<>) { 203 204 $line =~ s|[#!;].*$||; # get rid of a 205 $line =~ s|/\*.*\*/||; # ... and C-st 206 $line =~ s|^\s+||; # ... and skip 207 $line =~ s|\s+$||; # ... and at t 208 209 { 210 $line =~ s|\b\.L(\w+)|L$1|g; # comm 211 $line =~ s|\bL(\w+)|\.L$1|g if ($d 212 } 213 214 { 215 $line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s 216 my $c = $1; $c = "\t" if ($c eq ""); 217 my $mnemonic = $2; 218 my $f = $3; 219 my $opcode = eval("\$$mnemonic"); 220 $line =~ s/\b(c?[rf]|v|vs)([0-9]+)\b/$ 221 if (ref($opcode) eq 'CODE') { $line = 222 elsif ($mnemonic) { $line = 223 } 224 225 print $line if ($line); 226 print "\n"; 227 } 228 229 close STDOUT;
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.