summaryrefslogtreecommitdiffstats
path: root/crypto/sha/asm/sha1-s390x.pl
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/sha/asm/sha1-s390x.pl')
-rw-r--r--crypto/sha/asm/sha1-s390x.pl221
1 files changed, 221 insertions, 0 deletions
diff --git a/crypto/sha/asm/sha1-s390x.pl b/crypto/sha/asm/sha1-s390x.pl
new file mode 100644
index 0000000000..9f4436d525
--- /dev/null
+++ b/crypto/sha/asm/sha1-s390x.pl
@@ -0,0 +1,221 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# SHA1 block procedure for s390x.
+
+# April 2007.
+#
+# Performance is >30% better than gcc 3.3 generated code. But the real
+# twist is that SHA1 hardware support is detected and utilized. In
+# which case performance can reach further >8x for larger chunks.
+
+$kimdfunc=1; # magic function code for kimd instruction
+
+$output=shift;
+open STDOUT,">$output";
+
+$t0="%r0";
+$t1="%r1";
+$ctx="%r2";
+$inp="%r3";
+$len="%r4";
+
+$A="%r5";
+$B="%r6";
+$C="%r7";
+$D="%r8";
+$E="%r9"; @V=($A,$B,$C,$D,$E);
+$K_00_19="%r10";
+$K_20_39="%r11";
+$K_40_59="%r12";
+$K_60_79="%r13";
+$Xi="%r14";
+$sp="%r15";
+
+$frame=160+16*4;
+
+sub BODY_00_15 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $xi=($i&1)?$Xi:$t1;
+
+$code.=<<___ if ($i<16 && !($i&1));
+ lg $Xi,`$i*4`($inp)
+___
+$code.=<<___;
+ alr $e,$K_00_19 ### $i
+ rll $t0,$a,5
+ alr $e,$t0
+ lr $t0,$d
+ xr $t0,$c
+ nr $t0,$b
+ xr $t0,$d
+ alr $e,$t0
+ rll $b,$b,30
+___
+$code.=<<___ if ($i<16 && !($i&1));
+ srlg $xi,$Xi,32
+ stg $Xi,`160+$i*4`($sp)
+___
+$code.=<<___;
+ alr $e,$xi
+___
+}
+
+sub Xupdate {
+my $i=shift;
+
+return if ($i&1); # Xupdate is vectorized and executed every 2nd cycle
+$code.=<<___;
+ lg $Xi,`160+4*($i%16)`($sp) ### Xupdate($i)
+ xg $Xi,`160+4*(($i+2)%16)`($sp)
+ xg $Xi,`160+4*(($i+8)%16)`($sp)
+___
+if ((($i+13)%16)==15) {
+$code.=<<___;
+ llgf $t0,`160+4*15`($sp)
+ x $Xi,`160+0`($sp)
+ sllg $t0,$t0,32
+ xgr $Xi,$t0
+___
+} else {
+$code.=<<___;
+ xg $Xi,`160+4*(($i+13)%16)`($sp)
+___
+}
+$code.=<<___;
+ rll $Xi,$Xi,1
+ rllg $t1,$Xi,32
+ rll $t1,$t1,1
+ rllg $Xi,$t1,32
+ stg $Xi,`160+4*($i%16)`($sp)
+___
+}
+
+sub BODY_16_19 {
+ &Xupdate(@_[0]);
+ &BODY_00_15(@_);
+}
+
+sub BODY_20_39 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $xi=($i&1)?$Xi:$t1;
+my $K_XX_XX=($i<40)?$K_20_39:$K_60_79;
+
+ &Xupdate($i);
+$code.=<<___;
+ alr $e,$K_XX_XX ### $i
+ rll $t0,$a,5
+ alr $e,$t0
+ lr $t0,$b
+ xr $t0,$c
+ xr $t0,$d
+ alr $e,$t0
+ rll $b,$b,30
+ alr $e,$xi
+___
+}
+
+sub BODY_40_59 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $xi=($i&1)?$Xi:$t1;
+
+ &Xupdate($i);
+$code.=<<___;
+ alr $e,$K_40_59 ### $i
+ rll $t0,$a,5
+ alr $e,$t0
+ lr $t0,$b
+ or $t0,$c
+ nr $t0,$d
+ alr $e,$xi
+ lr $t1,$b
+ nr $t1,$c
+ or $t0,$t1
+ alr $e,$t0
+ rll $b,$b,30
+___
+}
+
+$code.=<<___;
+.text
+.globl sha1_block_data_order
+.type sha1_block_data_order,\@function
+sha1_block_data_order:
+___
+$code.=<<___ if ($kimdfunc);
+ lghi %r0,0
+ la %r1,16($sp)
+ .long 0xb93e0002 # kimd %r0,%r2
+ lg %r0,16($sp)
+ tmhh %r0,`0x8000>>$kimdfunc`
+ jz .Lsoftware
+ lghi %r0,$kimdfunc
+ lgr %r1,$ctx
+ lgr %r2,$inp
+ sllg %r3,$len,6
+ .long 0xb93e0002 # kimd %r0,%r2
+ br %r14
+.Lsoftware:
+___
+$code.=<<___;
+ stmg %r6,%r15,48($sp)
+ lgr %r0,$sp
+ aghi $sp,-$frame
+ stg %r0,0($sp)
+
+ sllg $len,$len,6
+ la $len,0($inp,$len)
+
+ llgf $A,0($ctx)
+ llgf $B,4($ctx)
+ llgf $C,8($ctx)
+ llgf $D,12($ctx)
+ llgf $E,16($ctx)
+
+ llilh $K_00_19,0x5a82
+ oill $K_00_19,0x7999
+ llilh $K_20_39,0x6ed9
+ oill $K_20_39,0xeba1
+ llilh $K_40_59,0x8f1b
+ oill $K_40_59,0xbcdc
+ llilh $K_60_79,0xca62
+ oill $K_60_79,0xc1d6
+.Lloop:
+___
+for ($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); }
+for (;$i<20;$i++) { &BODY_16_19($i,@V); unshift(@V,pop(@V)); }
+for (;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+for (;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
+for (;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+
+ al $A,0($ctx)
+ al $B,4($ctx)
+ al $C,8($ctx)
+ al $D,12($ctx)
+ al $E,16($ctx)
+ st $A,0($ctx)
+ st $B,4($ctx)
+ st $C,8($ctx)
+ st $D,12($ctx)
+ st $E,16($ctx)
+ la $inp,64($inp)
+ clgr $inp,$len
+ jne .Lloop
+
+ lmg %r6,%r15,`$frame+48`($sp)
+ br %r14
+.size sha1_block_data_order,.-sha1_block_data_order
+.string "SHA1 block transform for s390x, CRYPTOGAMS by <appro\@openssl.org>"
+___
+
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+
+print $code;
+close STDOUT;