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