diff options
author | Martin Schwenke <martin@meltin.net> | 2020-12-02 19:05:44 +1100 |
---|---|---|
committer | Pauli <pauli@openssl.org> | 2021-05-29 16:07:15 +1000 |
commit | 77112270593c4c51631e9138174f6657096399e9 (patch) | |
tree | bc1dbf2f559c070808808a9a24a58eef30228b88 /crypto | |
parent | 24c07e50551f73f565295db22478464ca9adc32e (diff) |
perlasm/ppc-xlate.pl: Handle rewriting of vector registers
Power has 2 numbering systems for vector registers:
* VR: Vector Registers are numbered from 0 to 31
* VSR: Vector-Scalar registers are numbers from 32 to 63
These refer to the same registers. Some instructions use VR numbering
for their operands, while others use VSR numbering.
When using Perl to provide a meaningful name for a register it makes
sense to use the same variable for both VR and VSR instructions. This
makes the code more readable.
However, providing a VSR number (i.e. >=32) to an instruction that
expects a VR number will cause an assembler error.
So, for instructions that require VR numbering, map VSR numbers
(i.e. >=32) to VR numbers. This also allows existing code that uses
VR numbering to remain unchanged.
Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15401)
Diffstat (limited to 'crypto')
-rwxr-xr-x | crypto/perlasm/ppc-xlate.pl | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/crypto/perlasm/ppc-xlate.pl b/crypto/perlasm/ppc-xlate.pl index 136e73e8af..14fd06dec4 100755 --- a/crypto/perlasm/ppc-xlate.pl +++ b/crypto/perlasm/ppc-xlate.pl @@ -136,6 +136,71 @@ my $quad = sub { }; ################################################################ +# vector register number hacking +################################################################ + +# It is convenient to be able to set a variable like: +# my $foo = "v33"; +# and use this in different contexts where: +# * a VSR (Vector-Scaler Register) number (i.e. "v33") is required +# * a VR (Vector Register) number (i.e. "v1") is required +# Map VSR numbering to VR number for certain vector instructions. + +# vs<N> -> v<N-32> if N > 32 +sub vsr2vr1 { + my $in = shift; + + my $n = int($in); + if ($n >= 32) { + $n -= 32; + } + + return "$n"; +} +# As above for first $num register args, returns list +sub _vsr2vr { + my $num = shift; + my @rest = @_; + my @subst = splice(@rest, 0, $num); + + @subst = map { vsr2vr1($_); } @subst; + + return (@subst, @rest); +} +# As above but 1st arg ($f) is extracted and reinserted after +# processing so that it can be ignored by a code generation function +# that consumes the result +sub vsr2vr_args { + my $num = shift; + my $f = shift; + + my @out = _vsr2vr($num, @_); + + return ($f, @out); +} +# As above but 1st arg is mnemonic, return formatted instruction +sub vsr2vr { + my $mnemonic = shift; + my $num = shift; + my $f = shift; + + my @out = _vsr2vr($num, @_); + + " ${mnemonic}${f} " . join(",", @out); +} + +# ISA 2.03 +my $vsel = sub { vsr2vr("vsel", 4, @_); }; +my $vsl = sub { vsr2vr("vsl", 3, @_); }; +my $vspltisb = sub { vsr2vr("vspltisb", 1, @_); }; +my $vspltisw = sub { vsr2vr("vspltisw", 1, @_); }; +my $vsr = sub { vsr2vr("vsr", 3, @_); }; +my $vsro = sub { vsr2vr("vsro", 3, @_); }; + +# ISA 3.0 +my $lxsd = sub { vsr2vr("lxsd", 1, @_); }; + +################################################################ # simplified mnemonics not handled by at least one assembler ################################################################ my $cmplw = sub { @@ -226,13 +291,18 @@ my $vpermdi = sub { # xxpermdi # PowerISA 2.07 stuff sub vcrypto_op { - my ($f, $vrt, $vra, $vrb, $op) = @_; + my ($f, $vrt, $vra, $vrb, $op) = vsr2vr_args(3, @_); " .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|$op; } sub vfour { my ($f, $vrt, $vra, $vrb, $vrc, $op) = @_; " .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($vrc<<6)|$op; }; +sub vfour_vsr { + my ($f, $vrt, $vra, $vrb, $vrc, $op) = vsr2vr_args(4, @_); + " .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($vrc<<6)|$op; +}; + my $vcipher = sub { vcrypto_op(@_, 1288); }; my $vcipherlast = sub { vcrypto_op(@_, 1289); }; my $vncipher = sub { vcrypto_op(@_, 1352); }; @@ -254,10 +324,10 @@ my $vsld = sub { vcrypto_op(@_, 1476); }; my $vsrd = sub { vcrypto_op(@_, 1732); }; my $vsubudm = sub { vcrypto_op(@_, 1216); }; my $vaddcuq = sub { vcrypto_op(@_, 320); }; -my $vaddeuqm = sub { vfour(@_,60); }; -my $vaddecuq = sub { vfour(@_,61); }; -my $vmrgew = sub { vfour(@_,0,1932); }; -my $vmrgow = sub { vfour(@_,0,1676); }; +my $vaddeuqm = sub { vfour_vsr(@_,60); }; +my $vaddecuq = sub { vfour_vsr(@_,61); }; +my $vmrgew = sub { vfour_vsr(@_,0,1932); }; +my $vmrgow = sub { vfour_vsr(@_,0,1676); }; my $mtsle = sub { my ($f, $arg) = @_; @@ -300,7 +370,7 @@ my $addex = sub { my ($f, $rt, $ra, $rb, $cy) = @_; # only cy==0 is specified in 3.0B " .long ".sprintf "0x%X",(31<<26)|($rt<<21)|($ra<<16)|($rb<<11)|($cy<<9)|(170<<1); }; -my $vmsumudm = sub { vfour(@_,35); }; +my $vmsumudm = sub { vfour_vsr(@_, 35); }; while($line=<>) { |