3 # ====================================================================
4 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
5 # project. The module is, however, dual licensed under OpenSSL and
6 # CRYPTOGAMS licenses depending on where you obtain it. For further
7 # details see http://www.openssl.org/~appro/cryptogams/.
8 # ====================================================================
10 # This module implements Poly1305 hash for s390x.
14 # ~6.4/2.2 cpb on z10/z196+, >2x improvement over compiler-generated
15 # code. For older compiler improvement coefficient is >3x, because
16 # then base 2^64 and base 2^32 implementations are compared.
18 # On side note, z13 enables vector base 2^26 implementation...
22 if ($flavour =~ /3[12]/) {
30 while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
31 open STDOUT,">$output";
35 my ($ctx,$inp,$len,$padbit) = map("%r$_",(2..5));
41 .type poly1305_init,\@function
46 stg %r0,0($ctx) # zero hash value
53 lrvg %r4,0($inp) # load little-endian key
56 nihl %r1,0xffc0 # 0xffffffc0ffffffff
57 srlg %r0,%r1,4 # 0x0ffffffc0fffffff
59 nill %r1,0xfffc # 0x0ffffffc0ffffffc
70 .size poly1305_init,.-poly1305_init
73 my ($d0hi,$d0lo,$d1hi,$d1lo,$t0,$h0,$t1,$h1,$h2) = map("%r$_",(6..14));
74 my ($r0,$r1,$s1) = map("%r$_",(0..2));
77 .globl poly1305_blocks
78 .type poly1305_blocks,\@function
81 srl${g} $len,4 # fixed-up in 64-bit build
86 stm${g} %r6,%r14,`6*$SIZE_T`($sp)
88 llgfr $padbit,$padbit # clear upper half, much needed with
90 lg $r0,32($ctx) # load key
93 lg $h0,0($ctx) # load hash value
97 st$g $ctx,`2*$SIZE_T`($sp) # off-load $ctx
99 algr $s1,$r1 # s1 = r1 + r1>>2
104 lrvg $d0lo,0($inp) # load little-endian input
108 algr $d0lo,$h0 # accumulate input
112 mlgr $d0hi,$r0 # h0*r0 -> $d0hi:$d0lo
114 mlgr $d1hi,$s1 # h1*5*r1 -> $d1hi:$d1lo
116 mlgr $t0,$r1 # h0*r1 -> $t0:$h0
117 mlgr $t1,$r0 # h1*r0 -> $t1:$h1
128 msgr $d1lo,$s1 # h2*s1
132 alcgr $t1,$d1hi # $d1hi is zero
137 lghi $h0,-4 # final reduction step
144 alcgr $h1,$d1hi # $d1hi is still zero
149 l$g $ctx,`2*$SIZE_T`($sp) # restore $ctx
151 stg $h0,0($ctx) # store hash value
155 lm${g} %r6,%r14,`6*$SIZE_T`($sp)
158 .size poly1305_blocks,.-poly1305_blocks
162 my ($mac,$nonce)=($inp,$len);
163 my ($h0,$h1,$h2,$d0,$d1)=map("%r$_",(5..9));
167 .type poly1305_emit,\@function
170 stm${g} %r6,%r9,`6*$SIZE_T`($sp)
181 algr $h0,%r0 # compare to modulus
185 srlg $h2,$h2,2 # did it borrow/carry?
186 slgr %r1,$h2 # 0-$h2>>2
187 lg $h2,0($nonce) # load nonce
197 rllg $d0,$h2,32 # flip nonce words
201 algr $h0,$d0 # accumulate nonce
204 strvg $h0,0($mac) # write little-endian result
207 lm${g} %r6,%r9,`6*$SIZE_T`($sp)
209 .size poly1305_emit,.-poly1305_emit
211 .string "Poly1305 for s390x, CRYPTOGAMS by <appro\@openssl.org>"
215 $code =~ s/\`([^\`]*)\`/eval $1/gem;
216 $code =~ s/\b(srlg\s+)(%r[0-9]+\s*,)\s*([0-9]+)/$1$2$2$3/gm;