linux/drivers/crypto/vmx/ppc-xlate.pl
<<
>>
Prefs
   1#!/usr/bin/env perl
   2# SPDX-License-Identifier: GPL-2.0
   3
   4# PowerPC assembler distiller by <appro>.
   5
   6my $flavour = shift;
   7my $output = shift;
   8open STDOUT,">$output" || die "can't open $output: $!";
   9
  10my %GLOBALS;
  11my $dotinlocallabels=($flavour=~/linux/)?1:0;
  12
  13################################################################
  14# directives which need special treatment on different platforms
  15################################################################
  16my $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 = ".$name";
  26                                last;
  27                              };
  28        /osx/           && do { $name = "_$name";
  29                                last;
  30                              };
  31        /linux/
  32                        && do { $ret = "_GLOBAL($name)";
  33                                last;
  34                              };
  35    }
  36
  37    $ret = ".globl      $name\nalign 5\n$name:" if (!$ret);
  38    $$global = $name;
  39    $ret;
  40};
  41my $text = sub {
  42    my $ret = ($flavour =~ /aix/) ? ".csect\t.text[PR],7" : ".text";
  43    $ret = ".abiversion 2\n".$ret       if ($flavour =~ /linux.*64le/);
  44    $ret;
  45};
  46my $machine = sub {
  47    my $junk = shift;
  48    my $arch = shift;
  49    if ($flavour =~ /osx/)
  50    {   $arch =~ s/\"//g;
  51        $arch = ($flavour=~/64/) ? "ppc970-64" : "ppc970" if ($arch eq "any");
  52    }
  53    ".machine   $arch";
  54};
  55my $size = sub {
  56    if ($flavour =~ /linux/)
  57    {   shift;
  58        my $name = shift; $name =~ s|^[\.\_]||;
  59        my $ret  = ".size       $name,.-".($flavour=~/64$/?".":"").$name;
  60        $ret .= "\n.size        .$name,.-.$name" if ($flavour=~/64$/);
  61        $ret;
  62    }
  63    else
  64    {   "";     }
  65};
  66my $asciz = sub {
  67    shift;
  68    my $line = join(",",@_);
  69    if ($line =~ /^"(.*)"$/)
  70    {   ".byte  " . join(",",unpack("C*",$1),0) . "\n.align     2";     }
  71    else
  72    {   "";     }
  73};
  74my $quad = sub {
  75    shift;
  76    my @ret;
  77    my ($hi,$lo);
  78    for (@_) {
  79        if (/^0x([0-9a-f]*?)([0-9a-f]{1,8})$/io)
  80        {  $hi=$1?"0x$1":"0"; $lo="0x$2";  }
  81        elsif (/^([0-9]+)$/o)
  82        {  $hi=$1>>32; $lo=$1&0xffffffff;  } # error-prone with 32-bit perl
  83        else
  84        {  $hi=undef; $lo=$_; }
  85
  86        if (defined($hi))
  87        {  push(@ret,$flavour=~/le$/o?".long\t$lo,$hi":".long\t$hi,$lo");  }
  88        else
  89        {  push(@ret,".quad     $lo");  }
  90    }
  91    join("\n",@ret);
  92};
  93
  94################################################################
  95# simplified mnemonics not handled by at least one assembler
  96################################################################
  97my $cmplw = sub {
  98    my $f = shift;
  99    my $cr = 0; $cr = shift if ($#_>1);
 100    # Some out-of-date 32-bit GNU assembler just can't handle cmplw...
 101    ($flavour =~ /linux.*32/) ?
 102        "       .long   ".sprintf "0x%x",31<<26|$cr<<23|$_[0]<<16|$_[1]<<11|64 :
 103        "       cmplw   ".join(',',$cr,@_);
 104};
 105my $bdnz = sub {
 106    my $f = shift;
 107    my $bo = $f=~/[\+\-]/ ? 16+9 : 16;  # optional "to be taken" hint
 108    "   bc      $bo,0,".shift;
 109} if ($flavour!~/linux/);
 110my $bltlr = sub {
 111    my $f = shift;
 112    my $bo = $f=~/\-/ ? 12+2 : 12;      # optional "not to be taken" hint
 113    ($flavour =~ /linux/) ?             # GNU as doesn't allow most recent hints
 114        "       .long   ".sprintf "0x%x",19<<26|$bo<<21|16<<1 :
 115        "       bclr    $bo,0";
 116};
 117my $bnelr = sub {
 118    my $f = shift;
 119    my $bo = $f=~/\-/ ? 4+2 : 4;        # optional "not to be taken" hint
 120    ($flavour =~ /linux/) ?             # GNU as doesn't allow most recent hints
 121        "       .long   ".sprintf "0x%x",19<<26|$bo<<21|2<<16|16<<1 :
 122        "       bclr    $bo,2";
 123};
 124my $beqlr = sub {
 125    my $f = shift;
 126    my $bo = $f=~/-/ ? 12+2 : 12;       # optional "not to be taken" hint
 127    ($flavour =~ /linux/) ?             # GNU as doesn't allow most recent hints
 128        "       .long   ".sprintf "0x%X",19<<26|$bo<<21|2<<16|16<<1 :
 129        "       bclr    $bo,2";
 130};
 131# GNU assembler can't handle extrdi rA,rS,16,48, or when sum of last two
 132# arguments is 64, with "operand out of range" error.
 133my $extrdi = sub {
 134    my ($f,$ra,$rs,$n,$b) = @_;
 135    $b = ($b+$n)&63; $n = 64-$n;
 136    "   rldicl  $ra,$rs,$b,$n";
 137};
 138my $vmr = sub {
 139    my ($f,$vx,$vy) = @_;
 140    "   vor     $vx,$vy,$vy";
 141};
 142
 143# Some ABIs specify vrsave, special-purpose register #256, as reserved
 144# for system use.
 145my $no_vrsave = ($flavour =~ /linux-ppc64le/);
 146my $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};
 154my $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
 164sub vsxmem_op {
 165    my ($f, $vrt, $ra, $rb, $op) = @_;
 166    "   .long   ".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|($rb<<11)|($op*2+1);
 167}
 168# made-up unaligned memory reference AltiVec/VMX instructions
 169my $lvx_u       = sub { vsxmem_op(@_, 844); };  # lxvd2x
 170my $stvx_u      = sub { vsxmem_op(@_, 972); };  # stxvd2x
 171my $lvdx_u      = sub { vsxmem_op(@_, 588); };  # lxsdx
 172my $stvdx_u     = sub { vsxmem_op(@_, 716); };  # stxsdx
 173my $lvx_4w      = sub { vsxmem_op(@_, 780); };  # lxvw4x
 174my $stvx_4w     = sub { vsxmem_op(@_, 908); };  # stxvw4x
 175
 176# PowerISA 2.07 stuff
 177sub vcrypto_op {
 178    my ($f, $vrt, $vra, $vrb, $op) = @_;
 179    "   .long   ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|$op;
 180}
 181my $vcipher     = sub { vcrypto_op(@_, 1288); };
 182my $vcipherlast = sub { vcrypto_op(@_, 1289); };
 183my $vncipher    = sub { vcrypto_op(@_, 1352); };
 184my $vncipherlast= sub { vcrypto_op(@_, 1353); };
 185my $vsbox       = sub { vcrypto_op(@_, 0, 1480); };
 186my $vshasigmad  = sub { my ($st,$six)=splice(@_,-2); vcrypto_op(@_, $st<<4|$six, 1730); };
 187my $vshasigmaw  = sub { my ($st,$six)=splice(@_,-2); vcrypto_op(@_, $st<<4|$six, 1666); };
 188my $vpmsumb     = sub { vcrypto_op(@_, 1032); };
 189my $vpmsumd     = sub { vcrypto_op(@_, 1224); };
 190my $vpmsubh     = sub { vcrypto_op(@_, 1096); };
 191my $vpmsumw     = sub { vcrypto_op(@_, 1160); };
 192my $vaddudm     = sub { vcrypto_op(@_, 192);  };
 193my $vadduqm     = sub { vcrypto_op(@_, 256);  };
 194
 195my $mtsle       = sub {
 196    my ($f, $arg) = @_;
 197    "   .long   ".sprintf "0x%X",(31<<26)|($arg<<21)|(147*2);
 198};
 199
 200print "#include <asm/ppc_asm.h>\n" if $flavour =~ /linux/;
 201
 202while($line=<>) {
 203
 204    $line =~ s|[#!;].*$||;      # get rid of asm-style comments...
 205    $line =~ s|/\*.*\*/||;      # ... and C-style comments...
 206    $line =~ s|^\s+||;          # ... and skip white spaces in beginning...
 207    $line =~ s|\s+$||;          # ... and at the end
 208
 209    {
 210        $line =~ s|\b\.L(\w+)|L$1|g;    # common denominator for Locallabel
 211        $line =~ s|\bL(\w+)|\.L$1|g     if ($dotinlocallabels);
 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/$2/g if ($c ne "." and $flavour !~ /osx/);
 221        if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(',',$line)); }
 222        elsif ($mnemonic)           { $line = $c.$mnemonic.$f."\t".$line; }
 223    }
 224
 225    print $line if ($line);
 226    print "\n";
 227}
 228
 229close STDOUT;
 230