summaryrefslogtreecommitdiffstats
path: root/crypto/perlasm
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2020-12-02 19:05:44 +1100
committerPauli <pauli@openssl.org>2021-05-29 16:07:15 +1000
commit77112270593c4c51631e9138174f6657096399e9 (patch)
treebc1dbf2f559c070808808a9a24a58eef30228b88 /crypto/perlasm
parent24c07e50551f73f565295db22478464ca9adc32e (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/perlasm')
-rwxr-xr-xcrypto/perlasm/ppc-xlate.pl82
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=<>) {