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