Fix some assembler generating scripts for better unification
[openssl.git] / crypto / poly1305 / asm / poly1305-s390x.pl
1 #!/usr/bin/env perl
2 #
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 # ====================================================================
9 #
10 # This module implements Poly1305 hash for s390x.
11 #
12 # June 2015
13 #
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.
17 #
18 # On side note, z13 enables vector base 2^26 implementation...
19
20 $flavour = shift;
21
22 if ($flavour =~ /3[12]/) {
23         $SIZE_T=4;
24         $g="";
25 } else {
26         $SIZE_T=8;
27         $g="g";
28 }
29
30 while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
31 open STDOUT,">$output";
32
33 $sp="%r15";
34
35 my ($ctx,$inp,$len,$padbit) = map("%r$_",(2..5));
36
37 $code.=<<___;
38 .text
39
40 .globl  poly1305_init
41 .type   poly1305_init,\@function
42 .align  16
43 poly1305_init:
44         lghi    %r0,0
45         lghi    %r1,-1
46         stg     %r0,0($ctx)             # zero hash value
47         stg     %r0,8($ctx)
48         stg     %r0,16($ctx)
49
50         cl${g}r $inp,%r0
51         je      .Lno_key
52
53         lrvg    %r4,0($inp)             # load little-endian key
54         lrvg    %r5,8($inp)
55
56         nihl    %r1,0xffc0              # 0xffffffc0ffffffff
57         srlg    %r0,%r1,4               # 0x0ffffffc0fffffff
58         srlg    %r1,%r1,4
59         nill    %r1,0xfffc              # 0x0ffffffc0ffffffc
60
61         ngr     %r4,%r0
62         ngr     %r5,%r1
63
64         stg     %r4,32($ctx)
65         stg     %r5,40($ctx)
66
67 .Lno_key:
68         lghi    %r2,0
69         br      %r14
70 .size   poly1305_init,.-poly1305_init
71 ___
72 {
73 my ($d0hi,$d0lo,$d1hi,$d1lo,$t0,$h0,$t1,$h1,$h2) = map("%r$_",(6..14));
74 my ($r0,$r1,$s1) = map("%r$_",(0..2));
75
76 $code.=<<___;
77 .globl  poly1305_blocks
78 .type   poly1305_blocks,\@function
79 .align  16
80 poly1305_blocks:
81         srl${g} $len,$len,4
82         lghi    %r0,0
83         cl${g}r $len,%r0
84         je      .Lno_data
85
86         stm${g} %r6,%r14,`6*$SIZE_T`($sp)
87
88         lg      $r0,32($ctx)            # load key
89         lg      $r1,40($ctx)
90
91         lg      $h0,0($ctx)             # load hash value
92         lg      $h1,8($ctx)
93         lg      $h2,16($ctx)
94
95         st$g    $ctx,`2*$SIZE_T`($sp)   # off-load $ctx
96         srlg    $s1,$r1,2
97         algr    $s1,$r1                 # s1 = r1 + r1>>2
98         j       .Loop
99
100 .align  16
101 .Loop:
102         lrvg    $d0lo,0($inp)           # load little-endian input
103         lrvg    $d1lo,8($inp)
104         la      $inp,16($inp)
105
106         algr    $d0lo,$h0               # accumulate input
107         alcgr   $d1lo,$h1
108
109         lgr     $h0,$d0lo
110         mlgr    $d0hi,$r0               # h0*r0   -> $d0hi:$d0lo
111         lgr     $h1,$d1lo
112         mlgr    $d1hi,$s1               # h1*5*r1 -> $d1hi:$d1lo
113
114         mlgr    $t0,$r1                 # h0*r1   -> $t0:$h0
115         mlgr    $t1,$r0                 # h1*r0   -> $t1:$h1
116         alcgr   $h2,$padbit
117
118         algr    $d0lo,$d1lo
119         lgr     $d1lo,$h2
120         alcgr   $d0hi,$d1hi
121         lghi    $d1hi,0
122
123         algr    $h1,$h0
124         alcgr   $t1,$t0
125
126         msgr    $d1lo,$s1               # h2*s1
127         msgr    $h2,$r0                 # h2*r0
128
129         algr    $h1,$d1lo
130         alcgr   $t1,$d1hi               # $d1hi is zero
131
132         algr    $h1,$d0hi
133         alcgr   $h2,$t1
134
135         lghi    $h0,-4                  # final reduction step
136         ngr     $h0,$h2
137         srlg    $t0,$h2,2
138         algr    $h0,$t0
139
140         algr    $h0,$d0lo
141         lghi    $t1,3
142         alcgr   $h1,$d1hi               # $d1hi is still zero
143         ngr     $h2,$t1
144
145         brct$g  $len,.Loop
146
147         l$g     $ctx,`2*$SIZE_T`($sp)   # restore $ctx
148
149         stg     $h0,0($ctx)             # store hash value
150         stg     $h1,8($ctx)
151         stg     $h2,16($ctx)
152
153         lm${g}  %r6,%r14,`6*$SIZE_T`($sp)
154 .Lno_data:
155         br      %r14
156 .size   poly1305_blocks,.-poly1305_blocks
157 ___
158 }
159 {
160 my ($mac,$nonce)=($inp,$len);
161 my ($h0,$h1,$h2,$d0,$d1)=map("%r$_",(5..9));
162
163 $code.=<<___;
164 .globl  poly1305_emit
165 .type   poly1305_emit,\@function
166 .align  16
167 poly1305_emit:
168         stm${g} %r6,%r9,`6*$SIZE_T`($sp)
169
170         lg      $h0,0($ctx)
171         lg      $h1,8($ctx)
172         lg      $h2,16($ctx)
173
174         lghi    %r0,5
175         lghi    %r1,0
176         lgr     $d0,$h0
177         lgr     $d1,$h1
178
179         algr    $h0,%r0                 # compare to modulus
180         alcgr   $h1,%r1
181         alcgr   $h2,%r1
182
183         srlg    $h2,$h2,2               # did it borrow/carry?
184         slgr    %r1,$h2                 # 0-$h2>>2
185         lg      $h2,0($nonce)           # load nonce
186         lghi    %r0,-1
187         lg      $ctx,8($nonce)
188         xgr     %r0,%r1                 # ~%r1
189
190         ngr     $h0,%r1
191         ngr     $d0,%r0
192         ngr     $h1,%r1
193         ngr     $d1,%r0
194         ogr     $h0,$d0
195         rllg    $d0,$h2,32              # flip nonce words
196         ogr     $h1,$d1
197         rllg    $d1,$ctx,32
198
199         algr    $h0,$d0                 # accumulate nonce
200         alcgr   $h1,$d1
201
202         strvg   $h0,0($mac)             # write little-endian result
203         strvg   $h1,8($mac)
204
205         lm${g}  %r6,%r9,`6*$SIZE_T`($sp)
206         br      %r14
207 .size   poly1305_emit,.-poly1305_emit
208
209 .string "Poly1305 for s390x, CRYPTOGAMS by <appro\@openssl.org>"
210 ___
211 }
212
213 $code =~ s/\`([^\`]*)\`/eval $1/gem;
214
215 print $code;
216 close STDOUT;