SPARCv9 assembly pack: unify build rules and argument handling.
[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 $output = pop;
72 open STDOUT,">$output";
73
74 $::evp=1;       # if $evp is set to 0, script generates module with
75 # AES_[en|de]crypt, AES_set_[en|de]crypt_key and AES_cbc_encrypt entry
76 # points. These however are not fully compatible with openssl/aes.h,
77 # because they expect AES_KEY to be aligned at 64-bit boundary. When
78 # used through EVP, alignment is arranged at EVP layer. Second thing
79 # that is arranged by EVP is at least 32-bit alignment of IV.
80
81 ######################################################################
82 # single-round subroutines
83 #
84 {
85 my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5));
86
87 $code.=<<___;
88 #include "sparc_arch.h"
89
90 #ifdef  __arch64__
91 .register       %g2,#scratch
92 .register       %g3,#scratch
93 #endif
94
95 .text
96
97 .globl  aes_t4_encrypt
98 .align  32
99 aes_t4_encrypt:
100         andcc           $inp, 7, %g1            ! is input aligned?
101         andn            $inp, 7, $inp
102
103         ldx             [$key + 0], %g4
104         ldx             [$key + 8], %g5
105
106         ldx             [$inp + 0], %o4
107         bz,pt           %icc, 1f
108         ldx             [$inp + 8], %o5
109         ldx             [$inp + 16], $inp
110         sll             %g1, 3, %g1
111         sub             %g0, %g1, %o3
112         sllx            %o4, %g1, %o4
113         sllx            %o5, %g1, %g1
114         srlx            %o5, %o3, %o5
115         srlx            $inp, %o3, %o3
116         or              %o5, %o4, %o4
117         or              %o3, %g1, %o5
118 1:
119         ld              [$key + 240], $rounds
120         ldd             [$key + 16], %f12
121         ldd             [$key + 24], %f14
122         xor             %g4, %o4, %o4
123         xor             %g5, %o5, %o5
124         movxtod         %o4, %f0
125         movxtod         %o5, %f2
126         srl             $rounds, 1, $rounds
127         ldd             [$key + 32], %f16
128         sub             $rounds, 1, $rounds
129         ldd             [$key + 40], %f18
130         add             $key, 48, $key
131
132 .Lenc:
133         aes_eround01    %f12, %f0, %f2, %f4
134         aes_eround23    %f14, %f0, %f2, %f2
135         ldd             [$key + 0], %f12
136         ldd             [$key + 8], %f14
137         sub             $rounds,1,$rounds
138         aes_eround01    %f16, %f4, %f2, %f0
139         aes_eround23    %f18, %f4, %f2, %f2
140         ldd             [$key + 16], %f16
141         ldd             [$key + 24], %f18
142         brnz,pt         $rounds, .Lenc
143         add             $key, 32, $key
144
145         andcc           $out, 7, $tmp           ! is output aligned?
146         aes_eround01    %f12, %f0, %f2, %f4
147         aes_eround23    %f14, %f0, %f2, %f2
148         aes_eround01_l  %f16, %f4, %f2, %f0
149         aes_eround23_l  %f18, %f4, %f2, %f2
150
151         bnz,pn          %icc, 2f
152         nop
153
154         std             %f0, [$out + 0]
155         retl
156         std             %f2, [$out + 8]
157
158 2:      alignaddrl      $out, %g0, $out
159         mov             0xff, $mask
160         srl             $mask, $tmp, $mask
161
162         faligndata      %f0, %f0, %f4
163         faligndata      %f0, %f2, %f6
164         faligndata      %f2, %f2, %f8
165
166         stda            %f4, [$out + $mask]0xc0 ! partial store
167         std             %f6, [$out + 8]
168         add             $out, 16, $out
169         orn             %g0, $mask, $mask
170         retl
171         stda            %f8, [$out + $mask]0xc0 ! partial store
172 .type   aes_t4_encrypt,#function
173 .size   aes_t4_encrypt,.-aes_t4_encrypt
174
175 .globl  aes_t4_decrypt
176 .align  32
177 aes_t4_decrypt:
178         andcc           $inp, 7, %g1            ! is input aligned?
179         andn            $inp, 7, $inp
180
181         ldx             [$key + 0], %g4
182         ldx             [$key + 8], %g5
183
184         ldx             [$inp + 0], %o4
185         bz,pt           %icc, 1f
186         ldx             [$inp + 8], %o5
187         ldx             [$inp + 16], $inp
188         sll             %g1, 3, %g1
189         sub             %g0, %g1, %o3
190         sllx            %o4, %g1, %o4
191         sllx            %o5, %g1, %g1
192         srlx            %o5, %o3, %o5
193         srlx            $inp, %o3, %o3
194         or              %o5, %o4, %o4
195         or              %o3, %g1, %o5
196 1:
197         ld              [$key + 240], $rounds
198         ldd             [$key + 16], %f12
199         ldd             [$key + 24], %f14
200         xor             %g4, %o4, %o4
201         xor             %g5, %o5, %o5
202         movxtod         %o4, %f0
203         movxtod         %o5, %f2
204         srl             $rounds, 1, $rounds
205         ldd             [$key + 32], %f16
206         sub             $rounds, 1, $rounds
207         ldd             [$key + 40], %f18
208         add             $key, 48, $key
209
210 .Ldec:
211         aes_dround01    %f12, %f0, %f2, %f4
212         aes_dround23    %f14, %f0, %f2, %f2
213         ldd             [$key + 0], %f12
214         ldd             [$key + 8], %f14
215         sub             $rounds,1,$rounds
216         aes_dround01    %f16, %f4, %f2, %f0
217         aes_dround23    %f18, %f4, %f2, %f2
218         ldd             [$key + 16], %f16
219         ldd             [$key + 24], %f18
220         brnz,pt         $rounds, .Ldec
221         add             $key, 32, $key
222
223         andcc           $out, 7, $tmp           ! is output aligned?
224         aes_dround01    %f12, %f0, %f2, %f4
225         aes_dround23    %f14, %f0, %f2, %f2
226         aes_dround01_l  %f16, %f4, %f2, %f0
227         aes_dround23_l  %f18, %f4, %f2, %f2
228
229         bnz,pn          %icc, 2f
230         nop
231
232         std             %f0, [$out + 0]
233         retl
234         std             %f2, [$out + 8]
235
236 2:      alignaddrl      $out, %g0, $out
237         mov             0xff, $mask
238         srl             $mask, $tmp, $mask
239
240         faligndata      %f0, %f0, %f4
241         faligndata      %f0, %f2, %f6
242         faligndata      %f2, %f2, %f8
243
244         stda            %f4, [$out + $mask]0xc0 ! partial store
245         std             %f6, [$out + 8]
246         add             $out, 16, $out
247         orn             %g0, $mask, $mask
248         retl
249         stda            %f8, [$out + $mask]0xc0 ! partial store
250 .type   aes_t4_decrypt,#function
251 .size   aes_t4_decrypt,.-aes_t4_decrypt
252 ___
253 }
254
255 ######################################################################
256 # key setup subroutines
257 #
258 {
259 my ($inp,$bits,$out,$tmp)=map("%o$_",(0..5));
260 $code.=<<___;
261 .globl  aes_t4_set_encrypt_key
262 .align  32
263 aes_t4_set_encrypt_key:
264 .Lset_encrypt_key:
265         and             $inp, 7, $tmp
266         alignaddr       $inp, %g0, $inp
267         cmp             $bits, 192
268         ldd             [$inp + 0], %f0
269         bl,pt           %icc,.L128
270         ldd             [$inp + 8], %f2
271
272         be,pt           %icc,.L192
273         ldd             [$inp + 16], %f4
274         brz,pt          $tmp, .L256aligned
275         ldd             [$inp + 24], %f6
276
277         ldd             [$inp + 32], %f8
278         faligndata      %f0, %f2, %f0
279         faligndata      %f2, %f4, %f2
280         faligndata      %f4, %f6, %f4
281         faligndata      %f6, %f8, %f6
282 .L256aligned:
283 ___
284 for ($i=0; $i<6; $i++) {
285     $code.=<<___;
286         std             %f0, [$out + `32*$i+0`]
287         aes_kexpand1    %f0, %f6, $i, %f0
288         std             %f2, [$out + `32*$i+8`]
289         aes_kexpand2    %f2, %f0, %f2
290         std             %f4, [$out + `32*$i+16`]
291         aes_kexpand0    %f4, %f2, %f4
292         std             %f6, [$out + `32*$i+24`]
293         aes_kexpand2    %f6, %f4, %f6
294 ___
295 }
296 $code.=<<___;
297         std             %f0, [$out + `32*$i+0`]
298         aes_kexpand1    %f0, %f6, $i, %f0
299         std             %f2, [$out + `32*$i+8`]
300         aes_kexpand2    %f2, %f0, %f2
301         std             %f4, [$out + `32*$i+16`]
302         std             %f6, [$out + `32*$i+24`]
303         std             %f0, [$out + `32*$i+32`]
304         std             %f2, [$out + `32*$i+40`]
305
306         mov             14, $tmp
307         st              $tmp, [$out + 240]
308         retl
309         xor             %o0, %o0, %o0
310
311 .align  16
312 .L192:
313         brz,pt          $tmp, .L192aligned
314         nop
315
316         ldd             [$inp + 24], %f6
317         faligndata      %f0, %f2, %f0
318         faligndata      %f2, %f4, %f2
319         faligndata      %f4, %f6, %f4
320 .L192aligned:
321 ___
322 for ($i=0; $i<7; $i++) {
323     $code.=<<___;
324         std             %f0, [$out + `24*$i+0`]
325         aes_kexpand1    %f0, %f4, $i, %f0
326         std             %f2, [$out + `24*$i+8`]
327         aes_kexpand2    %f2, %f0, %f2
328         std             %f4, [$out + `24*$i+16`]
329         aes_kexpand2    %f4, %f2, %f4
330 ___
331 }
332 $code.=<<___;
333         std             %f0, [$out + `24*$i+0`]
334         aes_kexpand1    %f0, %f4, $i, %f0
335         std             %f2, [$out + `24*$i+8`]
336         aes_kexpand2    %f2, %f0, %f2
337         std             %f4, [$out + `24*$i+16`]
338         std             %f0, [$out + `24*$i+24`]
339         std             %f2, [$out + `24*$i+32`]
340
341         mov             12, $tmp
342         st              $tmp, [$out + 240]
343         retl
344         xor             %o0, %o0, %o0
345
346 .align  16
347 .L128:
348         brz,pt          $tmp, .L128aligned
349         nop
350
351         ldd             [$inp + 16], %f4
352         faligndata      %f0, %f2, %f0
353         faligndata      %f2, %f4, %f2
354 .L128aligned:
355 ___
356 for ($i=0; $i<10; $i++) {
357     $code.=<<___;
358         std             %f0, [$out + `16*$i+0`]
359         aes_kexpand1    %f0, %f2, $i, %f0
360         std             %f2, [$out + `16*$i+8`]
361         aes_kexpand2    %f2, %f0, %f2
362 ___
363 }
364 $code.=<<___;
365         std             %f0, [$out + `16*$i+0`]
366         std             %f2, [$out + `16*$i+8`]
367
368         mov             10, $tmp
369         st              $tmp, [$out + 240]
370         retl
371         xor             %o0, %o0, %o0
372 .type   aes_t4_set_encrypt_key,#function
373 .size   aes_t4_set_encrypt_key,.-aes_t4_set_encrypt_key
374
375 .globl  aes_t4_set_decrypt_key
376 .align  32
377 aes_t4_set_decrypt_key:
378         mov             %o7, %o5
379         call            .Lset_encrypt_key
380         nop
381
382         mov             %o5, %o7
383         sll             $tmp, 4, $inp           ! $tmp is number of rounds
384         add             $tmp, 2, $tmp
385         add             $out, $inp, $inp        ! $inp=$out+16*rounds
386         srl             $tmp, 2, $tmp           ! $tmp=(rounds+2)/4
387
388 .Lkey_flip:
389         ldd             [$out + 0],  %f0
390         ldd             [$out + 8],  %f2
391         ldd             [$out + 16], %f4
392         ldd             [$out + 24], %f6
393         ldd             [$inp + 0],  %f8
394         ldd             [$inp + 8],  %f10
395         ldd             [$inp - 16], %f12
396         ldd             [$inp - 8],  %f14
397         sub             $tmp, 1, $tmp
398         std             %f0, [$inp + 0]
399         std             %f2, [$inp + 8]
400         std             %f4, [$inp - 16]
401         std             %f6, [$inp - 8]
402         std             %f8, [$out + 0]
403         std             %f10, [$out + 8]
404         std             %f12, [$out + 16]
405         std             %f14, [$out + 24]
406         add             $out, 32, $out
407         brnz            $tmp, .Lkey_flip
408         sub             $inp, 32, $inp
409
410         retl
411         xor             %o0, %o0, %o0
412 .type   aes_t4_set_decrypt_key,#function
413 .size   aes_t4_set_decrypt_key,.-aes_t4_set_decrypt_key
414 ___
415 }
416
417 {{{
418 my ($inp,$out,$len,$key,$ivec,$enc)=map("%i$_",(0..5));
419 my ($ileft,$iright,$ooff,$omask,$ivoff)=map("%l$_",(1..7));
420
421 $code.=<<___;
422 .align  32
423 _aes128_encrypt_1x:
424 ___
425 for ($i=0; $i<4; $i++) {
426     $code.=<<___;
427         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f4
428         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
429         aes_eround01    %f`16+8*$i+4`, %f4, %f2, %f0
430         aes_eround23    %f`16+8*$i+6`, %f4, %f2, %f2
431 ___
432 }
433 $code.=<<___;
434         aes_eround01    %f48, %f0, %f2, %f4
435         aes_eround23    %f50, %f0, %f2, %f2
436         aes_eround01_l  %f52, %f4, %f2, %f0
437         retl
438         aes_eround23_l  %f54, %f4, %f2, %f2
439 .type   _aes128_encrypt_1x,#function
440 .size   _aes128_encrypt_1x,.-_aes128_encrypt_1x
441
442 .align  32
443 _aes128_encrypt_2x:
444 ___
445 for ($i=0; $i<4; $i++) {
446     $code.=<<___;
447         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f8
448         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
449         aes_eround01    %f`16+8*$i+0`, %f4, %f6, %f10
450         aes_eround23    %f`16+8*$i+2`, %f4, %f6, %f6
451         aes_eround01    %f`16+8*$i+4`, %f8, %f2, %f0
452         aes_eround23    %f`16+8*$i+6`, %f8, %f2, %f2
453         aes_eround01    %f`16+8*$i+4`, %f10, %f6, %f4
454         aes_eround23    %f`16+8*$i+6`, %f10, %f6, %f6
455 ___
456 }
457 $code.=<<___;
458         aes_eround01    %f48, %f0, %f2, %f8
459         aes_eround23    %f50, %f0, %f2, %f2
460         aes_eround01    %f48, %f4, %f6, %f10
461         aes_eround23    %f50, %f4, %f6, %f6
462         aes_eround01_l  %f52, %f8, %f2, %f0
463         aes_eround23_l  %f54, %f8, %f2, %f2
464         aes_eround01_l  %f52, %f10, %f6, %f4
465         retl
466         aes_eround23_l  %f54, %f10, %f6, %f6
467 .type   _aes128_encrypt_2x,#function
468 .size   _aes128_encrypt_2x,.-_aes128_encrypt_2x
469
470 .align  32
471 _aes128_loadkey:
472         ldx             [$key + 0], %g4
473         ldx             [$key + 8], %g5
474 ___
475 for ($i=2; $i<22;$i++) {                        # load key schedule
476     $code.=<<___;
477         ldd             [$key + `8*$i`], %f`12+2*$i`
478 ___
479 }
480 $code.=<<___;
481         retl
482         nop
483 .type   _aes128_loadkey,#function
484 .size   _aes128_loadkey,.-_aes128_loadkey
485 _aes128_load_enckey=_aes128_loadkey
486 _aes128_load_deckey=_aes128_loadkey
487
488 ___
489
490 &alg_cbc_encrypt_implement("aes",128);
491 if ($::evp) {
492     &alg_ctr32_implement("aes",128);
493     &alg_xts_implement("aes",128,"en");
494     &alg_xts_implement("aes",128,"de");
495 }
496 &alg_cbc_decrypt_implement("aes",128);
497
498 $code.=<<___;
499 .align  32
500 _aes128_decrypt_1x:
501 ___
502 for ($i=0; $i<4; $i++) {
503     $code.=<<___;
504         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f4
505         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
506         aes_dround01    %f`16+8*$i+4`, %f4, %f2, %f0
507         aes_dround23    %f`16+8*$i+6`, %f4, %f2, %f2
508 ___
509 }
510 $code.=<<___;
511         aes_dround01    %f48, %f0, %f2, %f4
512         aes_dround23    %f50, %f0, %f2, %f2
513         aes_dround01_l  %f52, %f4, %f2, %f0
514         retl
515         aes_dround23_l  %f54, %f4, %f2, %f2
516 .type   _aes128_decrypt_1x,#function
517 .size   _aes128_decrypt_1x,.-_aes128_decrypt_1x
518
519 .align  32
520 _aes128_decrypt_2x:
521 ___
522 for ($i=0; $i<4; $i++) {
523     $code.=<<___;
524         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f8
525         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
526         aes_dround01    %f`16+8*$i+0`, %f4, %f6, %f10
527         aes_dround23    %f`16+8*$i+2`, %f4, %f6, %f6
528         aes_dround01    %f`16+8*$i+4`, %f8, %f2, %f0
529         aes_dround23    %f`16+8*$i+6`, %f8, %f2, %f2
530         aes_dround01    %f`16+8*$i+4`, %f10, %f6, %f4
531         aes_dround23    %f`16+8*$i+6`, %f10, %f6, %f6
532 ___
533 }
534 $code.=<<___;
535         aes_dround01    %f48, %f0, %f2, %f8
536         aes_dround23    %f50, %f0, %f2, %f2
537         aes_dround01    %f48, %f4, %f6, %f10
538         aes_dround23    %f50, %f4, %f6, %f6
539         aes_dround01_l  %f52, %f8, %f2, %f0
540         aes_dround23_l  %f54, %f8, %f2, %f2
541         aes_dround01_l  %f52, %f10, %f6, %f4
542         retl
543         aes_dround23_l  %f54, %f10, %f6, %f6
544 .type   _aes128_decrypt_2x,#function
545 .size   _aes128_decrypt_2x,.-_aes128_decrypt_2x
546 ___
547
548 $code.=<<___;
549 .align  32
550 _aes192_encrypt_1x:
551 ___
552 for ($i=0; $i<5; $i++) {
553     $code.=<<___;
554         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f4
555         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
556         aes_eround01    %f`16+8*$i+4`, %f4, %f2, %f0
557         aes_eround23    %f`16+8*$i+6`, %f4, %f2, %f2
558 ___
559 }
560 $code.=<<___;
561         aes_eround01    %f56, %f0, %f2, %f4
562         aes_eround23    %f58, %f0, %f2, %f2
563         aes_eround01_l  %f60, %f4, %f2, %f0
564         retl
565         aes_eround23_l  %f62, %f4, %f2, %f2
566 .type   _aes192_encrypt_1x,#function
567 .size   _aes192_encrypt_1x,.-_aes192_encrypt_1x
568
569 .align  32
570 _aes192_encrypt_2x:
571 ___
572 for ($i=0; $i<5; $i++) {
573     $code.=<<___;
574         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f8
575         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
576         aes_eround01    %f`16+8*$i+0`, %f4, %f6, %f10
577         aes_eround23    %f`16+8*$i+2`, %f4, %f6, %f6
578         aes_eround01    %f`16+8*$i+4`, %f8, %f2, %f0
579         aes_eround23    %f`16+8*$i+6`, %f8, %f2, %f2
580         aes_eround01    %f`16+8*$i+4`, %f10, %f6, %f4
581         aes_eround23    %f`16+8*$i+6`, %f10, %f6, %f6
582 ___
583 }
584 $code.=<<___;
585         aes_eround01    %f56, %f0, %f2, %f8
586         aes_eround23    %f58, %f0, %f2, %f2
587         aes_eround01    %f56, %f4, %f6, %f10
588         aes_eround23    %f58, %f4, %f6, %f6
589         aes_eround01_l  %f60, %f8, %f2, %f0
590         aes_eround23_l  %f62, %f8, %f2, %f2
591         aes_eround01_l  %f60, %f10, %f6, %f4
592         retl
593         aes_eround23_l  %f62, %f10, %f6, %f6
594 .type   _aes192_encrypt_2x,#function
595 .size   _aes192_encrypt_2x,.-_aes192_encrypt_2x
596
597 .align  32
598 _aes256_encrypt_1x:
599         aes_eround01    %f16, %f0, %f2, %f4
600         aes_eround23    %f18, %f0, %f2, %f2
601         ldd             [$key + 208], %f16
602         ldd             [$key + 216], %f18
603         aes_eround01    %f20, %f4, %f2, %f0
604         aes_eround23    %f22, %f4, %f2, %f2
605         ldd             [$key + 224], %f20
606         ldd             [$key + 232], %f22
607 ___
608 for ($i=1; $i<6; $i++) {
609     $code.=<<___;
610         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f4
611         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
612         aes_eround01    %f`16+8*$i+4`, %f4, %f2, %f0
613         aes_eround23    %f`16+8*$i+6`, %f4, %f2, %f2
614 ___
615 }
616 $code.=<<___;
617         aes_eround01    %f16, %f0, %f2, %f4
618         aes_eround23    %f18, %f0, %f2, %f2
619         ldd             [$key + 16], %f16
620         ldd             [$key + 24], %f18
621         aes_eround01_l  %f20, %f4, %f2, %f0
622         aes_eround23_l  %f22, %f4, %f2, %f2
623         ldd             [$key + 32], %f20
624         retl
625         ldd             [$key + 40], %f22
626 .type   _aes256_encrypt_1x,#function
627 .size   _aes256_encrypt_1x,.-_aes256_encrypt_1x
628
629 .align  32
630 _aes256_encrypt_2x:
631         aes_eround01    %f16, %f0, %f2, %f8
632         aes_eround23    %f18, %f0, %f2, %f2
633         aes_eround01    %f16, %f4, %f6, %f10
634         aes_eround23    %f18, %f4, %f6, %f6
635         ldd             [$key + 208], %f16
636         ldd             [$key + 216], %f18
637         aes_eround01    %f20, %f8, %f2, %f0
638         aes_eround23    %f22, %f8, %f2, %f2
639         aes_eround01    %f20, %f10, %f6, %f4
640         aes_eround23    %f22, %f10, %f6, %f6
641         ldd             [$key + 224], %f20
642         ldd             [$key + 232], %f22
643 ___
644 for ($i=1; $i<6; $i++) {
645     $code.=<<___;
646         aes_eround01    %f`16+8*$i+0`, %f0, %f2, %f8
647         aes_eround23    %f`16+8*$i+2`, %f0, %f2, %f2
648         aes_eround01    %f`16+8*$i+0`, %f4, %f6, %f10
649         aes_eround23    %f`16+8*$i+2`, %f4, %f6, %f6
650         aes_eround01    %f`16+8*$i+4`, %f8, %f2, %f0
651         aes_eround23    %f`16+8*$i+6`, %f8, %f2, %f2
652         aes_eround01    %f`16+8*$i+4`, %f10, %f6, %f4
653         aes_eround23    %f`16+8*$i+6`, %f10, %f6, %f6
654 ___
655 }
656 $code.=<<___;
657         aes_eround01    %f16, %f0, %f2, %f8
658         aes_eround23    %f18, %f0, %f2, %f2
659         aes_eround01    %f16, %f4, %f6, %f10
660         aes_eround23    %f18, %f4, %f6, %f6
661         ldd             [$key + 16], %f16
662         ldd             [$key + 24], %f18
663         aes_eround01_l  %f20, %f8, %f2, %f0
664         aes_eround23_l  %f22, %f8, %f2, %f2
665         aes_eround01_l  %f20, %f10, %f6, %f4
666         aes_eround23_l  %f22, %f10, %f6, %f6
667         ldd             [$key + 32], %f20
668         retl
669         ldd             [$key + 40], %f22
670 .type   _aes256_encrypt_2x,#function
671 .size   _aes256_encrypt_2x,.-_aes256_encrypt_2x
672
673 .align  32
674 _aes192_loadkey:
675         ldx             [$key + 0], %g4
676         ldx             [$key + 8], %g5
677 ___
678 for ($i=2; $i<26;$i++) {                        # load key schedule
679     $code.=<<___;
680         ldd             [$key + `8*$i`], %f`12+2*$i`
681 ___
682 }
683 $code.=<<___;
684         retl
685         nop
686 .type   _aes192_loadkey,#function
687 .size   _aes192_loadkey,.-_aes192_loadkey
688 _aes256_loadkey=_aes192_loadkey
689 _aes192_load_enckey=_aes192_loadkey
690 _aes192_load_deckey=_aes192_loadkey
691 _aes256_load_enckey=_aes192_loadkey
692 _aes256_load_deckey=_aes192_loadkey
693 ___
694
695 &alg_cbc_encrypt_implement("aes",256);
696 &alg_cbc_encrypt_implement("aes",192);
697 if ($::evp) {
698     &alg_ctr32_implement("aes",256);
699     &alg_xts_implement("aes",256,"en");
700     &alg_xts_implement("aes",256,"de");
701     &alg_ctr32_implement("aes",192);
702 }
703 &alg_cbc_decrypt_implement("aes",192);
704 &alg_cbc_decrypt_implement("aes",256);
705
706 $code.=<<___;
707 .align  32
708 _aes256_decrypt_1x:
709         aes_dround01    %f16, %f0, %f2, %f4
710         aes_dround23    %f18, %f0, %f2, %f2
711         ldd             [$key + 208], %f16
712         ldd             [$key + 216], %f18
713         aes_dround01    %f20, %f4, %f2, %f0
714         aes_dround23    %f22, %f4, %f2, %f2
715         ldd             [$key + 224], %f20
716         ldd             [$key + 232], %f22
717 ___
718 for ($i=1; $i<6; $i++) {
719     $code.=<<___;
720         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f4
721         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
722         aes_dround01    %f`16+8*$i+4`, %f4, %f2, %f0
723         aes_dround23    %f`16+8*$i+6`, %f4, %f2, %f2
724 ___
725 }
726 $code.=<<___;
727         aes_dround01    %f16, %f0, %f2, %f4
728         aes_dround23    %f18, %f0, %f2, %f2
729         ldd             [$key + 16], %f16
730         ldd             [$key + 24], %f18
731         aes_dround01_l  %f20, %f4, %f2, %f0
732         aes_dround23_l  %f22, %f4, %f2, %f2
733         ldd             [$key + 32], %f20
734         retl
735         ldd             [$key + 40], %f22
736 .type   _aes256_decrypt_1x,#function
737 .size   _aes256_decrypt_1x,.-_aes256_decrypt_1x
738
739 .align  32
740 _aes256_decrypt_2x:
741         aes_dround01    %f16, %f0, %f2, %f8
742         aes_dround23    %f18, %f0, %f2, %f2
743         aes_dround01    %f16, %f4, %f6, %f10
744         aes_dround23    %f18, %f4, %f6, %f6
745         ldd             [$key + 208], %f16
746         ldd             [$key + 216], %f18
747         aes_dround01    %f20, %f8, %f2, %f0
748         aes_dround23    %f22, %f8, %f2, %f2
749         aes_dround01    %f20, %f10, %f6, %f4
750         aes_dround23    %f22, %f10, %f6, %f6
751         ldd             [$key + 224], %f20
752         ldd             [$key + 232], %f22
753 ___
754 for ($i=1; $i<6; $i++) {
755     $code.=<<___;
756         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f8
757         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
758         aes_dround01    %f`16+8*$i+0`, %f4, %f6, %f10
759         aes_dround23    %f`16+8*$i+2`, %f4, %f6, %f6
760         aes_dround01    %f`16+8*$i+4`, %f8, %f2, %f0
761         aes_dround23    %f`16+8*$i+6`, %f8, %f2, %f2
762         aes_dround01    %f`16+8*$i+4`, %f10, %f6, %f4
763         aes_dround23    %f`16+8*$i+6`, %f10, %f6, %f6
764 ___
765 }
766 $code.=<<___;
767         aes_dround01    %f16, %f0, %f2, %f8
768         aes_dround23    %f18, %f0, %f2, %f2
769         aes_dround01    %f16, %f4, %f6, %f10
770         aes_dround23    %f18, %f4, %f6, %f6
771         ldd             [$key + 16], %f16
772         ldd             [$key + 24], %f18
773         aes_dround01_l  %f20, %f8, %f2, %f0
774         aes_dround23_l  %f22, %f8, %f2, %f2
775         aes_dround01_l  %f20, %f10, %f6, %f4
776         aes_dround23_l  %f22, %f10, %f6, %f6
777         ldd             [$key + 32], %f20
778         retl
779         ldd             [$key + 40], %f22
780 .type   _aes256_decrypt_2x,#function
781 .size   _aes256_decrypt_2x,.-_aes256_decrypt_2x
782
783 .align  32
784 _aes192_decrypt_1x:
785 ___
786 for ($i=0; $i<5; $i++) {
787     $code.=<<___;
788         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f4
789         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
790         aes_dround01    %f`16+8*$i+4`, %f4, %f2, %f0
791         aes_dround23    %f`16+8*$i+6`, %f4, %f2, %f2
792 ___
793 }
794 $code.=<<___;
795         aes_dround01    %f56, %f0, %f2, %f4
796         aes_dround23    %f58, %f0, %f2, %f2
797         aes_dround01_l  %f60, %f4, %f2, %f0
798         retl
799         aes_dround23_l  %f62, %f4, %f2, %f2
800 .type   _aes192_decrypt_1x,#function
801 .size   _aes192_decrypt_1x,.-_aes192_decrypt_1x
802
803 .align  32
804 _aes192_decrypt_2x:
805 ___
806 for ($i=0; $i<5; $i++) {
807     $code.=<<___;
808         aes_dround01    %f`16+8*$i+0`, %f0, %f2, %f8
809         aes_dround23    %f`16+8*$i+2`, %f0, %f2, %f2
810         aes_dround01    %f`16+8*$i+0`, %f4, %f6, %f10
811         aes_dround23    %f`16+8*$i+2`, %f4, %f6, %f6
812         aes_dround01    %f`16+8*$i+4`, %f8, %f2, %f0
813         aes_dround23    %f`16+8*$i+6`, %f8, %f2, %f2
814         aes_dround01    %f`16+8*$i+4`, %f10, %f6, %f4
815         aes_dround23    %f`16+8*$i+6`, %f10, %f6, %f6
816 ___
817 }
818 $code.=<<___;
819         aes_dround01    %f56, %f0, %f2, %f8
820         aes_dround23    %f58, %f0, %f2, %f2
821         aes_dround01    %f56, %f4, %f6, %f10
822         aes_dround23    %f58, %f4, %f6, %f6
823         aes_dround01_l  %f60, %f8, %f2, %f0
824         aes_dround23_l  %f62, %f8, %f2, %f2
825         aes_dround01_l  %f60, %f10, %f6, %f4
826         retl
827         aes_dround23_l  %f62, %f10, %f6, %f6
828 .type   _aes192_decrypt_2x,#function
829 .size   _aes192_decrypt_2x,.-_aes192_decrypt_2x
830 ___
831 }}}
832
833 if (!$::evp) {
834 $code.=<<___;
835 .global AES_encrypt
836 AES_encrypt=aes_t4_encrypt
837 .global AES_decrypt
838 AES_decrypt=aes_t4_decrypt
839 .global AES_set_encrypt_key
840 .align  32
841 AES_set_encrypt_key:
842         andcc           %o2, 7, %g0             ! check alignment
843         bnz,a,pn        %icc, 1f
844         mov             -1, %o0
845         brz,a,pn        %o0, 1f
846         mov             -1, %o0
847         brz,a,pn        %o2, 1f
848         mov             -1, %o0
849         andncc          %o1, 0x1c0, %g0
850         bnz,a,pn        %icc, 1f
851         mov             -2, %o0
852         cmp             %o1, 128
853         bl,a,pn         %icc, 1f
854         mov             -2, %o0
855         b               aes_t4_set_encrypt_key
856         nop
857 1:      retl
858         nop
859 .type   AES_set_encrypt_key,#function
860 .size   AES_set_encrypt_key,.-AES_set_encrypt_key
861
862 .global AES_set_decrypt_key
863 .align  32
864 AES_set_decrypt_key:
865         andcc           %o2, 7, %g0             ! check alignment
866         bnz,a,pn        %icc, 1f
867         mov             -1, %o0
868         brz,a,pn        %o0, 1f
869         mov             -1, %o0
870         brz,a,pn        %o2, 1f
871         mov             -1, %o0
872         andncc          %o1, 0x1c0, %g0
873         bnz,a,pn        %icc, 1f
874         mov             -2, %o0
875         cmp             %o1, 128
876         bl,a,pn         %icc, 1f
877         mov             -2, %o0
878         b               aes_t4_set_decrypt_key
879         nop
880 1:      retl
881         nop
882 .type   AES_set_decrypt_key,#function
883 .size   AES_set_decrypt_key,.-AES_set_decrypt_key
884 ___
885
886 my ($inp,$out,$len,$key,$ivec,$enc)=map("%o$_",(0..5));
887
888 $code.=<<___;
889 .globl  AES_cbc_encrypt
890 .align  32
891 AES_cbc_encrypt:
892         ld              [$key + 240], %g1
893         nop
894         brz             $enc, .Lcbc_decrypt
895         cmp             %g1, 12
896
897         bl,pt           %icc, aes128_t4_cbc_encrypt
898         nop
899         be,pn           %icc, aes192_t4_cbc_encrypt
900         nop
901         ba              aes256_t4_cbc_encrypt
902         nop
903
904 .Lcbc_decrypt:
905         bl,pt           %icc, aes128_t4_cbc_decrypt
906         nop
907         be,pn           %icc, aes192_t4_cbc_decrypt
908         nop
909         ba              aes256_t4_cbc_decrypt
910         nop
911 .type   AES_cbc_encrypt,#function
912 .size   AES_cbc_encrypt,.-AES_cbc_encrypt
913 ___
914 }
915 $code.=<<___;
916 .asciz  "AES for SPARC T4, David S. Miller, Andy Polyakov"
917 .align  4
918 ___
919
920 &emit_assembler();
921
922 close STDOUT;