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
86 stm${g} %r6,%r14,`6*$SIZE_T`($sp)
88 lg $r0,32($ctx) # load key
91 lg $h0,0($ctx) # load hash value
95 st$g $ctx,`2*$SIZE_T`($sp) # off-load $ctx
97 algr $s1,$r1 # s1 = r1 + r1>>2
102 lrvg $d0lo,0($inp) # load little-endian input
106 algr $d0lo,$h0 # accumulate input
110 mlgr $d0hi,$r0 # h0*r0 -> $d0hi:$d0lo
112 mlgr $d1hi,$s1 # h1*5*r1 -> $d1hi:$d1lo
114 mlgr $t0,$r1 # h0*r1 -> $t0:$h0
115 mlgr $t1,$r0 # h1*r0 -> $t1:$h1
126 msgr $d1lo,$s1 # h2*s1
130 alcgr $t1,$d1hi # $d1hi is zero
135 lghi $h0,-4 # final reduction step
142 alcgr $h1,$d1hi # $d1hi is still zero
147 l$g $ctx,`2*$SIZE_T`($sp) # restore $ctx
149 stg $h0,0($ctx) # store hash value
153 lm${g} %r6,%r14,`6*$SIZE_T`($sp)
156 .size poly1305_blocks,.-poly1305_blocks
160 my ($mac,$nonce)=($inp,$len);
161 my ($h0,$h1,$h2,$d0,$d1)=map("%r$_",(5..9));
165 .type poly1305_emit,\@function
168 stm${g} %r6,%r9,`6*$SIZE_T`($sp)
179 algr $h0,%r0 # compare to modulus
183 srlg $h2,$h2,2 # did it borrow/carry?
184 slgr %r1,$h2 # 0-$h2>>2
185 lg $h2,0($nonce) # load nonce
195 rllg $d0,$h2,32 # flip nonce words
199 algr $h0,$d0 # accumulate nonce
202 strvg $h0,0($mac) # write little-endian result
205 lm${g} %r6,%r9,`6*$SIZE_T`($sp)
207 .size poly1305_emit,.-poly1305_emit
209 .string "Poly1305 for s390x, CRYPTOGAMS by <appro\@openssl.org>"
213 $code =~ s/\`([^\`]*)\`/eval $1/gem;