aest4-sparcv9.pl: split it to AES-specific and reusable part.
[openssl.git] / crypto / aes / asm / aest4-sparcv9.pl
1 #!/usr/bin/env perl
2
3 # ====================================================================
4 # Written by David S. Miller <davem@devemloft.net> and Andy Polyakov
5 # <appro@openssl.org>. The module is licensed under 2-clause BSD
6 # license. October 2012. All rights reserved.
7 # ====================================================================
8
9 ######################################################################
10 # AES for SPARC T4.
11 #
12 # AES round instructions complete in 3 cycles and can be issued every
13 # cycle. It means that round calculations should take 4*rounds cycles,
14 # because any given round instruction depends on result of *both*
15 # previous instructions:
16 #
17 #       |0 |1 |2 |3 |4
18 #       |01|01|01|
19 #          |23|23|23|
20 #                   |01|01|...
21 #                      |23|...
22 #
23 # Provided that fxor [with IV] takes 3 cycles to complete, critical
24 # path length for CBC encrypt would be 3+4*rounds, or in other words
25 # it should process one byte in at least (3+4*rounds)/16 cycles. This
26 # estimate doesn't account for "collateral" instructions, such as
27 # fetching input from memory, xor-ing it with zero-round key and
28 # storing the result. Yet, *measured* performance [for data aligned
29 # at 64-bit boundary!] deviates from this equation by less than 0.5%:
30 #
31 #               128-bit key     192-            256-
32 # CBC encrypt   2.70/2.90(*)    3.20/3.40       3.70/3.90
33 #                        (*) numbers after slash are for
34 #                            misaligned data.
35 #
36 # Out-of-order execution logic managed to fully overlap "collateral"
37 # instructions with those on critical path. Amazing!
38 #
39 # As with Intel AES-NI, question is if it's possible to improve
40 # performance of parallelizeable modes by interleaving round
41 # instructions. Provided round instruction latency and throughput
42 # optimal interleave factor is 2. But can we expect 2x performance
43 # improvement? Well, as round instructions can be issued one per
44 # cycle, they don't saturate the 2-way issue pipeline and therefore
45 # there is room for "collateral" calculations... Yet, 2x speed-up
46 # over CBC encrypt remains unattaintable:
47 #
48 #               128-bit key     192-            256-
49 # CBC decrypt   1.64/2.11       1.89/2.37       2.23/2.61
50 # CTR           1.64/2.08(*)    1.89/2.33       2.23/2.61
51 #                        (*) numbers after slash are for
52 #                            misaligned data.
53 #
54 # Estimates based on amount of instructions under assumption that
55 # round instructions are not pairable with any other instruction
56 # suggest that latter is the actual case and pipeline runs
57 # underutilized. It should be noted that T4 out-of-order execution
58 # logic is so capable that performance gain from 2x interleave is
59 # not even impressive, ~7-13% over non-interleaved code, largest
60 # for 256-bit keys.
61
62 # To anchor to something else, software implementation processes
63 # one byte in 29 cycles with 128-bit key on same processor. Intel
64 # Sandy Bridge encrypts byte in 5.07 cycles in CBC mode and decrypts
65 # in 0.93, naturally with AES-NI.
66
67 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
68 push(@INC,"${dir}","${dir}../../perlasm");
69 require "sparcv9_modes.pl";
70
71 $bits=32;
72 for (@ARGV)     { $bits=64 if (/\-m64/ || /\-xarch\=v9/); }
73 if ($bits==64)  { $::bias=2047; $::frame=192; }
74 else            { $::bias=0;    $::frame=112; }
75
76 $::evp=1;       # if $evp is set to 0, script generates module with
77 # AES_[en|de]crypt, AES_set_[en|de]crypt_key and AES_cbc_encrypt entry
78 # points. These however are not fully compatible with openssl/aes.h,
79 # because they expect AES_KEY to be aligned at 64-bit boundary. When
80 # used through EVP, alignment is arranged at EVP layer. Second thing
81 # that is arranged by EVP is at least 32-bit alignment of IV.
82
83 ######################################################################
84 # single-round subroutines
85 #
86 {
87 my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5));
88
89 $code=<<___;
90 .text
91
92 .globl  aes_t4_encrypt
93 .align  32
94 aes_t4_encrypt:
95         andcc           $inp, 7, %g1            ! is input aligned?
96         andn            $inp, 7, $inp
97
98         ldx             [$key + 0], %g4
99         ldx             [$key + 8], %g5
100
101         ldx             [$inp + 0], %o4
102         bz,pt           %icc, 1f
103         ldx             [$inp + 8], %o5
104         ldx             [$inp + 16], $inp
105         sll             %g1, 3, %g1
106         sub             %g0, %g1, %o3
107         sllx            %o4, %g1, %o4
108         sllx            %o5, %g1, %g1
109         srlx            %o5, %o3, %o5
110         srlx            $inp, %o3, %o3
111         or              %o5, %o4, %o4
112         or              %o3, %g1, %o5
113 1:
114         ld              [$key + 240], $rounds
115         ldd             [$key + 16], %f12
116         ldd             [$key + 24], %f14
117         xor             %g4, %o4, %o4
118         xor             %g5, %o5, %o5
119         movxtod         %o4, %f0
120         movxtod         %o5, %f2
121         srl             $rounds, 1, $rounds
122         ldd             [$key + 32], %f16
123         sub             $rounds, 1, $rounds
124         ldd             [$key + 40], %f18
125         add             $key, 48, $key
126
127 .Lenc:
128         aes_eround01    %f12, %f0, %f2, %f4
129         aes_eround23    %f14, %f0, %f2, %f2
130         ldd             [$key + 0], %f12
131         ldd             [$key + 8], %f14
132         sub             $rounds,1,$rounds
133         aes_eround01    %f16, %f4, %f2, %f0
134         aes_eround23    %f18, %f4, %f2, %f2
135         ldd             [$key + 16], %f16
136         ldd             [$key + 24], %f18
137         brnz,pt         $rounds, .Lenc
138         add             $key, 32, $key
139
140         andcc           $out, 7, $tmp           ! is output aligned?
141         aes_eround01    %f12, %f0, %f2, %f4
142         aes_eround23    %f14, %f0, %f2, %f2
143         aes_eround01_l  %f16, %f4, %f2, %f0
144         aes_eround23_l  %f18, %f4, %f2, %f2
145
146         bnz,pn          %icc, 2f
147         nop
148
149         std             %f0, [$out + 0]
150         retl
151         std             %f2, [$out + 8]
152
153 2:      alignaddrl      $out, %g0, $out
154         mov             0xff, $mask
155         srl             $mask, $tmp, $mask
156
157         faligndata      %f0, %f0, %f4
158         faligndata      %f0, %f2, %f6
159         faligndata      %f2, %f2, %f8
160
161         stda            %f4, [$out + $mask]0xc0 ! partial store
162         std             %f6, [$out + 8]
163         add             $out, 16, $out
164         orn             %g0, $mask, $mask
165         retl
166         stda            %f8, [$out + $mask]0xc0 ! partial store
167 .type   aes_t4_encrypt,#function
168 .size   aes_t4_encrypt,.-aes_t4_encrypt
169
170 .globl  aes_t4_decrypt
171 .align  32
172 aes_t4_decrypt:
173         andcc           $inp, 7, %g1            ! is input aligned?
174         andn            $inp, 7, $inp
175
176         ldx             [$key + 0], %g4
177         ldx             [$key + 8], %g5
178
179         ldx             [$inp + 0], %o4
180         bz,pt           %icc, 1f
181         ldx             [$inp + 8], %o5
182         ldx             [$inp + 16], $inp
183         sll             %g1, 3, %g1
184         sub             %g0, %g1, %o3
185         sllx            %o4, %g1, %o4
186         sllx            %o5, %g1, %g1
187         srlx            %o5, %o3, %o5
188         srlx            $inp, %o3, %o3
189         or              %o5, %o4, %o4
190         or              %o3, %g1, %o5
191 1:
192         ld              [$key + 240], $rounds
193         ldd             [$key + 16], %f12
194         ldd             [$key + 24], %f14
195         xor             %g4, %o4, %o4
196         xor             %g5, %o5, %o5
197         movxtod         %o4, %f0
198         movxtod         %o5, %f2
199         srl             $rounds, 1, $rounds
200         ldd             [$key + 32], %f16
201         sub             $rounds, 1, $rounds
202         ldd             [$key + 40], %f18
203         add             $key, 48, $key
204
205 .Ldec:
206         aes_dround01    %f12, %f0, %f2, %f4
207         aes_dround23    %f14, %f0, %f2, %f2
208         ldd             [$key + 0], %f12
209         ldd             [$key + 8], %f14
210         sub             $rounds,1,$rounds
211         aes_dround01    %f16, %f4, %f2, %f0
212         aes_dround23    %f18, %f4, %f2, %f2
213         ldd             [$key + 16], %f16
214         ldd             [$key + 24], %f18
215         brnz,pt         $rounds, .Ldec
216         add             $key, 32, $key
217
218         andcc           $out, 7, $tmp           ! is output aligned?
219         aes_dround01    %f12, %f0, %f2, %f4
220         aes_dround23    %f14, %f0, %f2, %f2
221         aes_dround01_l  %f16, %f4, %f2, %f0
222         aes_dround23_l  %f18, %f4, %f2, %f2
223
224         bnz,pn          %icc, 2f
225         nop
226
227         std             %f0, [$out + 0]
228         retl
229         std             %f2, [$out + 8]
230
231 2:      alignaddrl      $out, %g0, $out
232         mov             0xff, $mask
233         srl             $mask, $tmp, $mask
234
235         faligndata      %f0, %f0, %f4
236         faligndata      %f0, %f2, %f6
237         faligndata      %f2, %f2, %f8
238
239         stda            %f4, [$out + $mask]0xc0 ! partial store
240         std             %f6, [$out + 8]
241         add             $out, 16, $out
242         orn             %g0, $mask, $mask
243         retl
244         stda            %f8, [$out + $mask]0xc0 ! partial store
245 .type   aes_t4_decrypt,#function
246 .size   aes_t4_decrypt,.-aes_t4_decrypt
247 ___
248 }
249
250 ######################################################################
251 # key setup subroutines
252 #
253 {
254 my ($inp,$bits,$out,$tmp)=map("%o$_",(0..5));
255 $code.=<<___;
256 .globl  aes_t4_set_encrypt_key
257 .align  32
258 aes_t4_set_encrypt_key:
259 .Lset_encrypt_key:
260         and             $inp, 7, $tmp
261         alignaddr       $inp, %g0, $inp
262         cmp             $bits, 192
263         ldd             [$inp + 0], %f0
264         bl,pt           %icc,.L128
265         ldd             [$inp + 8], %f2
266
267         be,pt           %icc,.L192
268         ldd             [$inp + 16], %f4
269         brz,pt          $tmp, .L256aligned
270         ldd             [$inp + 24], %f6
271
272         ldd             [$inp + 32], %f8
273         faligndata      %f0, %f2, %f0
274         faligndata      %f2, %f4, %f2
275         faligndata      %f4, %f6, %f4
276         faligndata      %f6, %f8, %f6
277 .L256aligned:
278 ___
279 for ($i=0; $i<6; $i++) {
280     $code.=<<___;
281         std             %f0, [$out + `32*$i+0`]
282         aes_kexpand1    %f0, %f6, $i, %f0
283         std             %f2, [$out + `32*$i+8`]
284         aes_kexpand2    %f2, %f0, %f2
285         std             %f4, [$out + `32*$i+16`]
286         aes_kexpand0    %f4, %f2, %f4
287         std             %f6, [$out + `32*$i+24`]
288         aes_kexpand2    %f6, %f4, %f6
289 ___
290 }
291 $code.=<<___;
292         std             %f0, [$out + `32*$i+0`]
293         aes_kexpand1    %f0, %f6, $i, %f0
294         std             %f2, [$out + `32*$i+8`]
295         aes_kexpand2    %f2, %f0, %f2
296         std             %f4, [$out + `32*$i+16`]
297         std             %f6, [$out + `32*$i+24`]
298         std             %f0, [$out + `32*$i+32`]
299         std             %f2, [$out + `32*$i+40`]
300
301         mov             14, $tmp
302         st              $tmp, [$out + 240]
303         retl
304         xor             %o0, %o0, %o0
305
306 .align  16
307 .L192:
308         brz,pt          $tmp, .L192aligned
309         nop
310
311         ldd             [$inp + 24], %f6
312         faligndata      %f0, %f2, %f0
313         faligndata      %f2, %f4, %f2
314         faligndata      %f4, %f6, %f4
315 .L192aligned:
316 ___
317 for ($i=0; $i<7; $i++) {
318     $code.=<<___;
319         std             %f0, [$out + `24*$i+0`]
320         aes_kexpand1    %f0, %f4, $i, %f0
321         std             %f2, [$out + `24*$i+8`]
322         aes_kexpand2    %f2, %f0, %f2
323         std             %f4, [$out + `24*$i+16`]
324         aes_kexpand2    %f4, %f2, %f4
325 ___
326 }
327 $code.=<<___;
328         std             %f0, [$out + `24*$i+0`]
329         aes_kexpand1    %f0, %f4, $i, %f0
330         std             %f2, [$out + `24*$i+8`]
331         aes_kexpand2    %f2, %f0, %f2
332         std             %f4, [$out + `24*$i+16`]
333         std             %f0, [$out + `24*$i+24`]
334         std             %f2, [$out + `24*$i+32`]
335
336         mov             12, $tmp
337         st              $tmp, [$out + 240]
338         retl
339         xor             %o0, %o0, %o0
340
341 .align  16
342 .L128:
343         brz,pt          $tmp, .L128aligned
344         nop
345
346         ldd             [$inp + 16], %f4
347         faligndata      %f0, %f2, %f0
348         faligndata      %f2, %f4, %f2
349 .L128aligned:
350 ___
351 for ($i=0; $i<10; $i++) {
352     $code.=<<___;
353         std             %f0, [$out + `16*$i+0`]
354         aes_kexpand1    %f0, %f2, $i, %f0
355         std             %f2, [$out + `16*$i+8`]
356         aes_kexpand2    %f2, %f0, %f2
357 ___
358 }
359 $code.=<<___;
360         std             %f0, [$out + `16*$i+0`]
361         std             %f2, [$out + `16*$i+8`]
362
363         mov             10, $tmp
364         st              $tmp, [$out + 240]
365         retl
366         xor             %o0, %o0, %o0
367 .type   aes_t4_set_encrypt_key,#function
368 .size   aes_t4_set_encrypt_key,.-aes_t4_set_encrypt_key
369
370 .globl  aes_t4_set_decrypt_key
371 .align  32
372 aes_t4_set_decrypt_key:
373         mov             %o7, %o5
374         call            .Lset_encrypt_key
375         nop
376
377         mov             %o5, %o7
378         sll             $tmp, 4, $inp           ! $tmp is number of rounds
379         add             $tmp, 2, $tmp
380         add             $out, $inp, $inp        ! $inp=$out+16*rounds
381         srl             $tmp, 2, $tmp           ! $tmp=(rounds+2)/4
382
383 .Lkey_flip:
384         ldd             [$out + 0],  %f0
385         ldd             [$out + 8],  %f2
386         ldd             [$out + 16], %f4
387         ldd             [$out + 24], %f6
388         ldd             [$inp + 0],  %f8
389         ldd             [$inp + 8],  %f10
390         ldd             [$inp - 16], %f12
391         ldd             [$inp - 8],  %f14
392         sub             $tmp, 1, $tmp
393         std             %f0, [$inp + 0]
394         std             %f2, [$inp + 8]
395         std             %f4, [$inp - 16]
396         std             %f6, [$inp - 8]
397         std             %f8, [$out + 0]
398         std             %f10, [$out + 8]
399         std             %f12, [$out + 16]
400         std             %f14, [$out + 24]
401         add             $out, 32, $out
402         brnz            $tmp, .Lkey_flip
403         sub             $inp, 32, $inp
404
405         retl
406         xor             %o0, %o0, %o0
407 .type   aes_t4_set_decrypt_key,#function
408 .size   aes_t4_set_decrypt_key,.-aes_t4_set_decrypt_key
409 ___
410 }
411
412 {{{
413 my ($inp,$out,$len,$key,$ivec,$enc)=map("%i$_",(0..5));
414 my ($ileft,$iright,$ooff,$omask,$ivoff)=map("%l$_",(1..7));
415
416 $code.=<<___;
417 .align  32
418 _aes128_loadkey:
419         ldx             [$key + 0], %g4
420         ldx             [$key + 8], %g5
421 ___
422 for ($i=2; $i<22;$i++) {                        # load key schedule
423     $code.=<<___;
424         ldd             [$key + `8*$i`], %f`12+2*$i`
425 ___
426 }
427 $code.=<<___;
428         retl
429         nop
430 .type   _aes128_loadkey,#function
431 .size   _aes128_loadkey,.-_aes128_loadkey
432 _aes128_load_enckey=_aes128_loadkey
433 _aes128_load_deckey=_aes128_loadkey
434
435 .align  32
436 _aes128_encrypt_1x:
437 ___
438 for ($i=0; $i<4; $i++) {
439     $code.=<<___;
440         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f4
441         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
442         aes_eround01    %f`16+8*$i+4`, %f4, %f2, %f0
443         aes_eround23    %f`16+8*$i+6`, %f4, %f2, %f2
444 ___
445 }
446 $code.=<<___;
447         aes_eround01    %f48, %f0, %f2, %f4
448         aes_eround23    %f50, %f0, %f2, %f2
449         aes_eround01_l  %f52, %f4, %f2, %f0
450         retl
451         aes_eround23_l  %f54, %f4, %f2, %f2
452 .type   _aes128_encrypt_1x,#function
453 .size   _aes128_encrypt_1x,.-_aes128_encrypt_1x
454
455 .align  32
456 _aes128_encrypt_2x:
457 ___
458 for ($i=0; $i<4; $i++) {
459     $code.=<<___;
460         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f8
461         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
462         aes_eround01    %f`16+8*$i+0`, %f4, %f6, %f10
463         aes_eround23    %f`16+8*$i+2`, %f4, %f6, %f6
464         aes_eround01    %f`16+8*$i+4`, %f8, %f2, %f0
465         aes_eround23    %f`16+8*$i+6`, %f8, %f2, %f2
466         aes_eround01    %f`16+8*$i+4`, %f10, %f6, %f4
467         aes_eround23    %f`16+8*$i+6`, %f10, %f6, %f6
468 ___
469 }
470 $code.=<<___;
471         aes_eround01    %f48, %f0, %f2, %f8
472         aes_eround23    %f50, %f0, %f2, %f2
473         aes_eround01    %f48, %f4, %f6, %f10
474         aes_eround23    %f50, %f4, %f6, %f6
475         aes_eround01_l  %f52, %f8, %f2, %f0
476         aes_eround23_l  %f54, %f8, %f2, %f2
477         aes_eround01_l  %f52, %f10, %f6, %f4
478         retl
479         aes_eround23_l  %f54, %f10, %f6, %f6
480 .type   _aes128_encrypt_2x,#function
481 .size   _aes128_encrypt_2x,.-_aes128_encrypt_2x
482
483 .align  32
484 _aes128_decrypt_1x:
485 ___
486 for ($i=0; $i<4; $i++) {
487     $code.=<<___;
488         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f4
489         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
490         aes_dround01    %f`16+8*$i+4`, %f4, %f2, %f0
491         aes_dround23    %f`16+8*$i+6`, %f4, %f2, %f2
492 ___
493 }
494 $code.=<<___;
495         aes_dround01    %f48, %f0, %f2, %f4
496         aes_dround23    %f50, %f0, %f2, %f2
497         aes_dround01_l  %f52, %f4, %f2, %f0
498         retl
499         aes_dround23_l  %f54, %f4, %f2, %f2
500 .type   _aes128_decrypt_1x,#function
501 .size   _aes128_decrypt_1x,.-_aes128_decrypt_1x
502
503 .align  32
504 _aes128_decrypt_2x:
505 ___
506 for ($i=0; $i<4; $i++) {
507     $code.=<<___;
508         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f8
509         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
510         aes_dround01    %f`16+8*$i+0`, %f4, %f6, %f10
511         aes_dround23    %f`16+8*$i+2`, %f4, %f6, %f6
512         aes_dround01    %f`16+8*$i+4`, %f8, %f2, %f0
513         aes_dround23    %f`16+8*$i+6`, %f8, %f2, %f2
514         aes_dround01    %f`16+8*$i+4`, %f10, %f6, %f4
515         aes_dround23    %f`16+8*$i+6`, %f10, %f6, %f6
516 ___
517 }
518 $code.=<<___;
519         aes_dround01    %f48, %f0, %f2, %f8
520         aes_dround23    %f50, %f0, %f2, %f2
521         aes_dround01    %f48, %f4, %f6, %f10
522         aes_dround23    %f50, %f4, %f6, %f6
523         aes_dround01_l  %f52, %f8, %f2, %f0
524         aes_dround23_l  %f54, %f8, %f2, %f2
525         aes_dround01_l  %f52, %f10, %f6, %f4
526         retl
527         aes_dround23_l  %f54, %f10, %f6, %f6
528 .type   _aes128_decrypt_2x,#function
529 .size   _aes128_decrypt_2x,.-_aes128_decrypt_2x
530
531 .align  32
532 _aes192_loadkey:
533 _aes256_loadkey:
534         ldx             [$key + 0], %g4
535         ldx             [$key + 8], %g5
536 ___
537 for ($i=2; $i<26;$i++) {                        # load key schedule
538     $code.=<<___;
539         ldd             [$key + `8*$i`], %f`12+2*$i`
540 ___
541 }
542 $code.=<<___;
543         retl
544         nop
545 .type   _aes192_loadkey,#function
546 .size   _aes192_loadkey,.-_aes192_loadkey
547 _aes192_load_enckey=_aes192_loadkey
548 _aes192_load_deckey=_aes192_loadkey
549 _aes256_load_enckey=_aes192_loadkey
550 _aes256_load_deckey=_aes192_loadkey
551
552 .align  32
553 _aes192_encrypt_1x:
554 ___
555 for ($i=0; $i<5; $i++) {
556     $code.=<<___;
557         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f4
558         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
559         aes_eround01    %f`16+8*$i+4`, %f4, %f2, %f0
560         aes_eround23    %f`16+8*$i+6`, %f4, %f2, %f2
561 ___
562 }
563 $code.=<<___;
564         aes_eround01    %f56, %f0, %f2, %f4
565         aes_eround23    %f58, %f0, %f2, %f2
566         aes_eround01_l  %f60, %f4, %f2, %f0
567         retl
568         aes_eround23_l  %f62, %f4, %f2, %f2
569 .type   _aes192_encrypt_1x,#function
570 .size   _aes192_encrypt_1x,.-_aes192_encrypt_1x
571
572 .align  32
573 _aes192_encrypt_2x:
574 ___
575 for ($i=0; $i<5; $i++) {
576     $code.=<<___;
577         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f8
578         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
579         aes_eround01    %f`16+8*$i+0`, %f4, %f6, %f10
580         aes_eround23    %f`16+8*$i+2`, %f4, %f6, %f6
581         aes_eround01    %f`16+8*$i+4`, %f8, %f2, %f0
582         aes_eround23    %f`16+8*$i+6`, %f8, %f2, %f2
583         aes_eround01    %f`16+8*$i+4`, %f10, %f6, %f4
584         aes_eround23    %f`16+8*$i+6`, %f10, %f6, %f6
585 ___
586 }
587 $code.=<<___;
588         aes_eround01    %f56, %f0, %f2, %f8
589         aes_eround23    %f58, %f0, %f2, %f2
590         aes_eround01    %f56, %f4, %f6, %f10
591         aes_eround23    %f58, %f4, %f6, %f6
592         aes_eround01_l  %f60, %f8, %f2, %f0
593         aes_eround23_l  %f62, %f8, %f2, %f2
594         aes_eround01_l  %f60, %f10, %f6, %f4
595         retl
596         aes_eround23_l  %f62, %f10, %f6, %f6
597 .type   _aes192_encrypt_2x,#function
598 .size   _aes192_encrypt_2x,.-_aes192_encrypt_2x
599
600 .align  32
601 _aes192_decrypt_1x:
602 ___
603 for ($i=0; $i<5; $i++) {
604     $code.=<<___;
605         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f4
606         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
607         aes_dround01    %f`16+8*$i+4`, %f4, %f2, %f0
608         aes_dround23    %f`16+8*$i+6`, %f4, %f2, %f2
609 ___
610 }
611 $code.=<<___;
612         aes_dround01    %f56, %f0, %f2, %f4
613         aes_dround23    %f58, %f0, %f2, %f2
614         aes_dround01_l  %f60, %f4, %f2, %f0
615         retl
616         aes_dround23_l  %f62, %f4, %f2, %f2
617 .type   _aes192_decrypt_1x,#function
618 .size   _aes192_decrypt_1x,.-_aes192_decrypt_1x
619
620 .align  32
621 _aes192_decrypt_2x:
622 ___
623 for ($i=0; $i<5; $i++) {
624     $code.=<<___;
625         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f8
626         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
627         aes_dround01    %f`16+8*$i+0`, %f4, %f6, %f10
628         aes_dround23    %f`16+8*$i+2`, %f4, %f6, %f6
629         aes_dround01    %f`16+8*$i+4`, %f8, %f2, %f0
630         aes_dround23    %f`16+8*$i+6`, %f8, %f2, %f2
631         aes_dround01    %f`16+8*$i+4`, %f10, %f6, %f4
632         aes_dround23    %f`16+8*$i+6`, %f10, %f6, %f6
633 ___
634 }
635 $code.=<<___;
636         aes_dround01    %f56, %f0, %f2, %f8
637         aes_dround23    %f58, %f0, %f2, %f2
638         aes_dround01    %f56, %f4, %f6, %f10
639         aes_dround23    %f58, %f4, %f6, %f6
640         aes_dround01_l  %f60, %f8, %f2, %f0
641         aes_dround23_l  %f62, %f8, %f2, %f2
642         aes_dround01_l  %f60, %f10, %f6, %f4
643         retl
644         aes_dround23_l  %f62, %f10, %f6, %f6
645 .type   _aes192_decrypt_2x,#function
646 .size   _aes192_decrypt_2x,.-_aes192_decrypt_2x
647
648 .align  32
649 _aes256_encrypt_1x:
650         aes_eround01    %f16, %f0, %f2, %f4
651         aes_eround23    %f18, %f0, %f2, %f2
652         ldd             [$key + 208], %f16
653         ldd             [$key + 216], %f18
654         aes_eround01    %f20, %f4, %f2, %f0
655         aes_eround23    %f22, %f4, %f2, %f2
656         ldd             [$key + 224], %f20
657         ldd             [$key + 232], %f22
658 ___
659 for ($i=1; $i<6; $i++) {
660     $code.=<<___;
661         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f4
662         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
663         aes_eround01    %f`16+8*$i+4`, %f4, %f2, %f0
664         aes_eround23    %f`16+8*$i+6`, %f4, %f2, %f2
665 ___
666 }
667 $code.=<<___;
668         aes_eround01    %f16, %f0, %f2, %f4
669         aes_eround23    %f18, %f0, %f2, %f2
670         ldd             [$key + 16], %f16
671         ldd             [$key + 24], %f18
672         aes_eround01_l  %f20, %f4, %f2, %f0
673         aes_eround23_l  %f22, %f4, %f2, %f2
674         ldd             [$key + 32], %f20
675         retl
676         ldd             [$key + 40], %f22
677 .type   _aes256_encrypt_1x,#function
678 .size   _aes256_encrypt_1x,.-_aes256_encrypt_1x
679
680 .align  32
681 _aes256_encrypt_2x:
682         aes_eround01    %f16, %f0, %f2, %f8
683         aes_eround23    %f18, %f0, %f2, %f2
684         aes_eround01    %f16, %f4, %f6, %f10
685         aes_eround23    %f18, %f4, %f6, %f6
686         ldd             [$key + 208], %f16
687         ldd             [$key + 216], %f18
688         aes_eround01    %f20, %f8, %f2, %f0
689         aes_eround23    %f22, %f8, %f2, %f2
690         aes_eround01    %f20, %f10, %f6, %f4
691         aes_eround23    %f22, %f10, %f6, %f6
692         ldd             [$key + 224], %f20
693         ldd             [$key + 232], %f22
694 ___
695 for ($i=1; $i<6; $i++) {
696     $code.=<<___;
697         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f8
698         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
699         aes_eround01    %f`16+8*$i+0`, %f4, %f6, %f10
700         aes_eround23    %f`16+8*$i+2`, %f4, %f6, %f6
701         aes_eround01    %f`16+8*$i+4`, %f8, %f2, %f0
702         aes_eround23    %f`16+8*$i+6`, %f8, %f2, %f2
703         aes_eround01    %f`16+8*$i+4`, %f10, %f6, %f4
704         aes_eround23    %f`16+8*$i+6`, %f10, %f6, %f6
705 ___
706 }
707 $code.=<<___;
708         aes_eround01    %f16, %f0, %f2, %f8
709         aes_eround23    %f18, %f0, %f2, %f2
710         aes_eround01    %f16, %f4, %f6, %f10
711         aes_eround23    %f18, %f4, %f6, %f6
712         ldd             [$key + 16], %f16
713         ldd             [$key + 24], %f18
714         aes_eround01_l  %f20, %f8, %f2, %f0
715         aes_eround23_l  %f22, %f8, %f2, %f2
716         aes_eround01_l  %f20, %f10, %f6, %f4
717         aes_eround23_l  %f22, %f10, %f6, %f6
718         ldd             [$key + 32], %f20
719         retl
720         ldd             [$key + 40], %f22
721 .type   _aes256_encrypt_2x,#function
722 .size   _aes256_encrypt_2x,.-_aes256_encrypt_2x
723
724 .align  32
725 _aes256_decrypt_1x:
726         aes_dround01    %f16, %f0, %f2, %f4
727         aes_dround23    %f18, %f0, %f2, %f2
728         ldd             [$key + 208], %f16
729         ldd             [$key + 216], %f18
730         aes_dround01    %f20, %f4, %f2, %f0
731         aes_dround23    %f22, %f4, %f2, %f2
732         ldd             [$key + 224], %f20
733         ldd             [$key + 232], %f22
734 ___
735 for ($i=1; $i<6; $i++) {
736     $code.=<<___;
737         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f4
738         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
739         aes_dround01    %f`16+8*$i+4`, %f4, %f2, %f0
740         aes_dround23    %f`16+8*$i+6`, %f4, %f2, %f2
741 ___
742 }
743 $code.=<<___;
744         aes_dround01    %f16, %f0, %f2, %f4
745         aes_dround23    %f18, %f0, %f2, %f2
746         ldd             [$key + 16], %f16
747         ldd             [$key + 24], %f18
748         aes_dround01_l  %f20, %f4, %f2, %f0
749         aes_dround23_l  %f22, %f4, %f2, %f2
750         ldd             [$key + 32], %f20
751         retl
752         ldd             [$key + 40], %f22
753 .type   _aes256_decrypt_1x,#function
754 .size   _aes256_decrypt_1x,.-_aes256_decrypt_1x
755
756 .align  32
757 _aes256_decrypt_2x:
758         aes_dround01    %f16, %f0, %f2, %f8
759         aes_dround23    %f18, %f0, %f2, %f2
760         aes_dround01    %f16, %f4, %f6, %f10
761         aes_dround23    %f18, %f4, %f6, %f6
762         ldd             [$key + 208], %f16
763         ldd             [$key + 216], %f18
764         aes_dround01    %f20, %f8, %f2, %f0
765         aes_dround23    %f22, %f8, %f2, %f2
766         aes_dround01    %f20, %f10, %f6, %f4
767         aes_dround23    %f22, %f10, %f6, %f6
768         ldd             [$key + 224], %f20
769         ldd             [$key + 232], %f22
770 ___
771 for ($i=1; $i<6; $i++) {
772     $code.=<<___;
773         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f8
774         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
775         aes_dround01    %f`16+8*$i+0`, %f4, %f6, %f10
776         aes_dround23    %f`16+8*$i+2`, %f4, %f6, %f6
777         aes_dround01    %f`16+8*$i+4`, %f8, %f2, %f0
778         aes_dround23    %f`16+8*$i+6`, %f8, %f2, %f2
779         aes_dround01    %f`16+8*$i+4`, %f10, %f6, %f4
780         aes_dround23    %f`16+8*$i+6`, %f10, %f6, %f6
781 ___
782 }
783 $code.=<<___;
784         aes_dround01    %f16, %f0, %f2, %f8
785         aes_dround23    %f18, %f0, %f2, %f2
786         aes_dround01    %f16, %f4, %f6, %f10
787         aes_dround23    %f18, %f4, %f6, %f6
788         ldd             [$key + 16], %f16
789         ldd             [$key + 24], %f18
790         aes_dround01_l  %f20, %f8, %f2, %f0
791         aes_dround23_l  %f22, %f8, %f2, %f2
792         aes_dround01_l  %f20, %f10, %f6, %f4
793         aes_dround23_l  %f22, %f10, %f6, %f6
794         ldd             [$key + 32], %f20
795         retl
796         ldd             [$key + 40], %f22
797 .type   _aes256_decrypt_2x,#function
798 .size   _aes256_decrypt_2x,.-_aes256_decrypt_2x
799 ___
800
801 &alg_cbc_encrypt_implement("aes",128);
802 &alg_cbc_encrypt_implement("aes",192);
803 &alg_cbc_encrypt_implement("aes",256);
804
805 &alg_cbc_decrypt_implement("aes",128);
806 &alg_cbc_decrypt_implement("aes",192);
807 &alg_cbc_decrypt_implement("aes",256);
808
809 if ($::evp) {
810     &alg_ctr32_implement("aes",128);
811     &alg_ctr32_implement("aes",192);
812     &alg_ctr32_implement("aes",256);
813 }
814 }}}
815
816 if (!$::evp) {
817 $code.=<<___;
818 .global AES_encrypt
819 AES_encrypt=aes_t4_encrypt
820 .global AES_decrypt
821 AES_decrypt=aes_t4_decrypt
822 .global AES_set_encrypt_key
823 .align  32
824 AES_set_encrypt_key:
825         andcc           %o2, 7, %g0             ! check alignment
826         bnz,a,pn        %icc, 1f
827         mov             -1, %o0
828         brz,a,pn        %o0, 1f
829         mov             -1, %o0
830         brz,a,pn        %o2, 1f
831         mov             -1, %o0
832         andncc          %o1, 0x1c0, %g0
833         bnz,a,pn        %icc, 1f
834         mov             -2, %o0
835         cmp             %o1, 128
836         bl,a,pn         %icc, 1f
837         mov             -2, %o0
838         b               aes_t4_set_encrypt_key
839         nop
840 1:      retl
841         nop
842 .type   AES_set_encrypt_key,#function
843 .size   AES_set_encrypt_key,.-AES_set_encrypt_key
844
845 .global AES_set_decrypt_key
846 .align  32
847 AES_set_decrypt_key:
848         andcc           %o2, 7, %g0             ! check alignment
849         bnz,a,pn        %icc, 1f
850         mov             -1, %o0
851         brz,a,pn        %o0, 1f
852         mov             -1, %o0
853         brz,a,pn        %o2, 1f
854         mov             -1, %o0
855         andncc          %o1, 0x1c0, %g0
856         bnz,a,pn        %icc, 1f
857         mov             -2, %o0
858         cmp             %o1, 128
859         bl,a,pn         %icc, 1f
860         mov             -2, %o0
861         b               aes_t4_set_decrypt_key
862         nop
863 1:      retl
864         nop
865 .type   AES_set_decrypt_key,#function
866 .size   AES_set_decrypt_key,.-AES_set_decrypt_key
867 ___
868
869 my ($inp,$out,$len,$key,$ivec,$enc)=map("%o$_",(0..5));
870
871 $code.=<<___;
872 .globl  AES_cbc_encrypt
873 .align  32
874 AES_cbc_encrypt:
875         ld              [$key + 240], %g1
876         nop
877         brz             $enc, .Lcbc_decrypt
878         cmp             %g1, 12
879
880         bl,pt           %icc, aes128_t4_cbc_encrypt
881         nop
882         be,pn           %icc, aes192_t4_cbc_encrypt
883         nop
884         ba              aes256_t4_cbc_encrypt
885         nop
886
887 .Lcbc_decrypt:
888         bl,pt           %icc, aes128_t4_cbc_decrypt
889         nop
890         be,pn           %icc, aes192_t4_cbc_decrypt
891         nop
892         ba              aes256_t4_cbc_decrypt
893         nop
894 .type   AES_cbc_encrypt,#function
895 .size   AES_cbc_encrypt,.-AES_cbc_encrypt
896 ___
897 }
898 $code.=<<___;
899 .asciz  "AES for SPARC T4, David S. Miller, Andy Polyakov"
900 .align  4
901 ___
902
903 &emit_assembler();
904
905 close STDOUT;