a813168b42ec47b4b0af702fab6d15ea55ecedf6
[openssl.git] / crypto / camellia / asm / cmllt4-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 # Camellia for SPARC T4.
11 #
12 # As with AES below results [for aligned data] are virtually identical
13 # to critical path lenths for 3-cycle instruction latency:
14 #
15 #               128-bit key     192/256-
16 # CBC encrypt   4.14/4.21(*)    5.46/5.52
17 #                        (*) numbers after slash are for
18 #                            misaligned data.
19 #
20 # As with Intel AES-NI, question is if it's possible to improve
21 # performance of parallelizeable modes by interleaving round
22 # instructions. In Camellia every instruction is dependent on
23 # previous, which means that there is place for 2 additional ones
24 # in between two dependent. Can we expect 3x performance improvement?
25 # At least one can argue that it should be possible to break 2x
26 # barrier... For some reason not even 2x appears to be possible:
27 #
28 #               128-bit key     192/256-
29 # CBC decrypt   2.21/2.74       2.99/3.40
30 # CTR           2.15/2.68(*)    2.93/3.34
31 #                        (*) numbers after slash are for
32 #                            misaligned data.
33 #
34 # This is for 2x interleave. But compared to 1x interleave CBC decrypt
35 # improved by ... 0% for 128-bit key, and 11% for 192/256-bit one.
36 # So that out-of-order execution logic can take non-interleaved code
37 # to 1.87x, but can't take 2x interleaved one any further. There
38 # surely is some explanation... As result 3x interleave was not even
39 # attempted. Instead an effort was made to share specific modes
40 # implementations with AES module (therefore sparct4_modes.pl).
41 #
42 # To anchor to something else, software C implementation processes
43 # one byte in 38 cycles with 128-bit key on same processor.
44
45 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
46 push(@INC,"${dir}","${dir}../../perlasm");
47 require "sparcv9_modes.pl";
48
49 &asm_init(@ARGV);
50
51 $::evp=1;       # if $evp is set to 0, script generates module with
52 # Camellia_[en|de]crypt, Camellia_set_key and Camellia_cbc_encrypt
53 # entry points. These are fully compatible with openssl/camellia.h.
54
55 ######################################################################
56 # single-round subroutines
57 #
58 {
59 my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5));
60
61 $code=<<___;
62 .text
63
64 .globl  cmll_t4_encrypt
65 .align  32
66 cmll_t4_encrypt:
67         andcc           $inp, 7, %g1            ! is input aligned?
68         andn            $inp, 7, $inp
69
70         ldx             [$key + 0], %g4
71         ldx             [$key + 8], %g5
72
73         ldx             [$inp + 0], %o4
74         bz,pt           %icc, 1f
75         ldx             [$inp + 8], %o5
76         ldx             [$inp + 16], $inp
77         sll             %g1, 3, %g1
78         sub             %g0, %g1, %o3
79         sllx            %o4, %g1, %o4
80         sllx            %o5, %g1, %g1
81         srlx            %o5, %o3, %o5
82         srlx            $inp, %o3, %o3
83         or              %o5, %o4, %o4
84         or              %o3, %g1, %o5
85 1:
86         ld              [$key + 272], $rounds   ! grandRounds, 3 or 4
87         ldd             [$key + 16], %f12
88         ldd             [$key + 24], %f14
89         xor             %g4, %o4, %o4
90         xor             %g5, %o5, %o5
91         ldd             [$key + 32], %f16
92         ldd             [$key + 40], %f18
93         movxtod         %o4, %f0
94         movxtod         %o5, %f2
95         ldd             [$key + 48], %f20
96         ldd             [$key + 56], %f22
97         sub             $rounds, 1, $rounds
98         ldd             [$key + 64], %f24
99         ldd             [$key + 72], %f26
100         add             $key, 80, $key
101
102 .Lenc:
103         camellia_f      %f12, %f2, %f0, %f2
104         ldd             [$key + 0], %f12
105         sub             $rounds,1,$rounds
106         camellia_f      %f14, %f0, %f2, %f0
107         ldd             [$key + 8], %f14
108         camellia_f      %f16, %f2, %f0, %f2
109         ldd             [$key + 16], %f16
110         camellia_f      %f18, %f0, %f2, %f0
111         ldd             [$key + 24], %f18
112         camellia_f      %f20, %f2, %f0, %f2
113         ldd             [$key + 32], %f20
114         camellia_f      %f22, %f0, %f2, %f0
115         ldd             [$key + 40], %f22
116         camellia_fl     %f24, %f0, %f0
117         ldd             [$key + 48], %f24
118         camellia_fli    %f26, %f2, %f2
119         ldd             [$key + 56], %f26
120         brnz,pt         $rounds, .Lenc
121         add             $key, 64, $key
122
123         andcc           $out, 7, $tmp           ! is output aligned?
124         camellia_f      %f12, %f2, %f0, %f2
125         camellia_f      %f14, %f0, %f2, %f0
126         camellia_f      %f16, %f2, %f0, %f2
127         camellia_f      %f18, %f0, %f2, %f0
128         camellia_f      %f20, %f2, %f0, %f4
129         camellia_f      %f22, %f0, %f4, %f2
130         fxor            %f24, %f4, %f0
131         fxor            %f26, %f2, %f2
132
133         bnz,pn          %icc, 2f
134         nop
135
136         std             %f0, [$out + 0]
137         retl
138         std             %f2, [$out + 8]
139
140 2:      alignaddrl      $out, %g0, $out
141         mov             0xff, $mask
142         srl             $mask, $tmp, $mask
143
144         faligndata      %f0, %f0, %f4
145         faligndata      %f0, %f2, %f6
146         faligndata      %f2, %f2, %f8
147
148         stda            %f4, [$out + $mask]0xc0 ! partial store
149         std             %f6, [$out + 8]
150         add             $out, 16, $out
151         orn             %g0, $mask, $mask
152         retl
153         stda            %f8, [$out + $mask]0xc0 ! partial store
154 .type   cmll_t4_encrypt,#function
155 .size   cmll_t4_encrypt,.-cmll_t4_encrypt
156
157 .globl  cmll_t4_decrypt
158 .align  32
159 cmll_t4_decrypt:
160         ld              [$key + 272], $rounds   ! grandRounds, 3 or 4
161         andcc           $inp, 7, %g1            ! is input aligned?
162         andn            $inp, 7, $inp
163
164         sll             $rounds, 6, $rounds
165         add             $rounds, $key, $key
166
167         ldx             [$inp + 0], %o4
168         bz,pt           %icc, 1f
169         ldx             [$inp + 8], %o5
170         ldx             [$inp + 16], $inp
171         sll             %g1, 3, %g1
172         sub             %g0, %g1, %g4
173         sllx            %o4, %g1, %o4
174         sllx            %o5, %g1, %g1
175         srlx            %o5, %g4, %o5
176         srlx            $inp, %g4, %g4
177         or              %o5, %o4, %o4
178         or              %g4, %g1, %o5
179 1:
180         ldx             [$key + 0], %g4
181         ldx             [$key + 8], %g5
182         ldd             [$key - 8], %f12
183         ldd             [$key - 16], %f14
184         xor             %g4, %o4, %o4
185         xor             %g5, %o5, %o5
186         ldd             [$key - 24], %f16
187         ldd             [$key - 32], %f18
188         movxtod         %o4, %f0
189         movxtod         %o5, %f2
190         ldd             [$key - 40], %f20
191         ldd             [$key - 48], %f22
192         sub             $rounds, 64, $rounds
193         ldd             [$key - 56], %f24
194         ldd             [$key - 64], %f26
195         sub             $key, 64, $key
196
197 .Ldec:
198         camellia_f      %f12, %f2, %f0, %f2
199         ldd             [$key - 8], %f12
200         sub             $rounds, 64, $rounds
201         camellia_f      %f14, %f0, %f2, %f0
202         ldd             [$key - 16], %f14
203         camellia_f      %f16, %f2, %f0, %f2
204         ldd             [$key - 24], %f16
205         camellia_f      %f18, %f0, %f2, %f0
206         ldd             [$key - 32], %f18
207         camellia_f      %f20, %f2, %f0, %f2
208         ldd             [$key - 40], %f20
209         camellia_f      %f22, %f0, %f2, %f0
210         ldd             [$key - 48], %f22
211         camellia_fl     %f24, %f0, %f0
212         ldd             [$key - 56], %f24
213         camellia_fli    %f26, %f2, %f2
214         ldd             [$key - 64], %f26
215         brnz,pt         $rounds, .Ldec
216         sub             $key, 64, $key
217
218         andcc           $out, 7, $tmp           ! is output aligned?
219         camellia_f      %f12, %f2, %f0, %f2
220         camellia_f      %f14, %f0, %f2, %f0
221         camellia_f      %f16, %f2, %f0, %f2
222         camellia_f      %f18, %f0, %f2, %f0
223         camellia_f      %f20, %f2, %f0, %f4
224         camellia_f      %f22, %f0, %f4, %f2
225         fxor            %f26, %f4, %f0
226         fxor            %f24, %f2, %f2
227
228         bnz,pn          %icc, 2f
229         nop
230
231         std             %f0, [$out + 0]
232         retl
233         std             %f2, [$out + 8]
234
235 2:      alignaddrl      $out, %g0, $out
236         mov             0xff, $mask
237         srl             $mask, $tmp, $mask
238
239         faligndata      %f0, %f0, %f4
240         faligndata      %f0, %f2, %f6
241         faligndata      %f2, %f2, %f8
242
243         stda            %f4, [$out + $mask]0xc0 ! partial store
244         std             %f6, [$out + 8]
245         add             $out, 16, $out
246         orn             %g0, $mask, $mask
247         retl
248         stda            %f8, [$out + $mask]0xc0 ! partial store
249 .type   cmll_t4_decrypt,#function
250 .size   cmll_t4_decrypt,.-cmll_t4_decrypt
251 ___
252 }
253
254 ######################################################################
255 # key setup subroutines
256 #
257 {
258 sub ROTL128 {
259   my $rot = shift;
260
261         "srlx   %o4, 64-$rot, %g4\n\t".
262         "sllx   %o4, $rot, %o4\n\t".
263         "srlx   %o5, 64-$rot, %g5\n\t".
264         "sllx   %o5, $rot, %o5\n\t".
265         "or     %o4, %g5, %o4\n\t".
266         "or     %o5, %g4, %o5";
267 }
268
269 my ($inp,$bits,$out,$tmp)=map("%o$_",(0..5));
270 $code.=<<___;
271 .globl  cmll_t4_set_key
272 .align  32
273 cmll_t4_set_key:
274         and             $inp, 7, $tmp
275         alignaddr       $inp, %g0, $inp
276         cmp             $bits, 192
277         ldd             [$inp + 0], %f0
278         bl,pt           %icc,.L128
279         ldd             [$inp + 8], %f2
280
281         be,pt           %icc,.L192
282         ldd             [$inp + 16], %f4
283
284         brz,pt          $tmp, .L256aligned
285         ldd             [$inp + 24], %f6
286
287         ldd             [$inp + 32], %f8
288         faligndata      %f0, %f2, %f0
289         faligndata      %f2, %f4, %f2
290         faligndata      %f4, %f6, %f4
291         b               .L256aligned
292         faligndata      %f6, %f8, %f6
293
294 .align  16
295 .L192:
296         brz,a,pt        $tmp, .L256aligned
297         fnot2           %f4, %f6
298
299         ldd             [$inp + 24], %f6
300         nop
301         faligndata      %f0, %f2, %f0
302         faligndata      %f2, %f4, %f2
303         faligndata      %f4, %f6, %f4
304         fnot2           %f4, %f6
305
306 .L256aligned:
307         std             %f0, [$out + 0]         ! k[0, 1]
308         fsrc2           %f0, %f28
309         std             %f2, [$out + 8]         ! k[2, 3]
310         fsrc2           %f2, %f30
311         fxor            %f4, %f0, %f0
312         b               .L128key
313         fxor            %f6, %f2, %f2
314
315 .align  16
316 .L128:
317         brz,pt          $tmp, .L128aligned
318         nop
319
320         ldd             [$inp + 16], %f4
321         nop
322         faligndata      %f0, %f2, %f0
323         faligndata      %f2, %f4, %f2
324
325 .L128aligned:
326         std             %f0, [$out + 0]         ! k[0, 1]
327         fsrc2           %f0, %f28
328         std             %f2, [$out + 8]         ! k[2, 3]
329         fsrc2           %f2, %f30
330
331 .L128key:
332         mov             %o7, %o5
333 1:      call            .+8
334         add             %o7, SIGMA-1b, %o4
335         mov             %o5, %o7
336
337         ldd             [%o4 + 0], %f16
338         ldd             [%o4 + 8], %f18
339         ldd             [%o4 + 16], %f20
340         ldd             [%o4 + 24], %f22
341
342         camellia_f      %f16, %f2, %f0, %f2
343         camellia_f      %f18, %f0, %f2, %f0
344         fxor            %f28, %f0, %f0
345         fxor            %f30, %f2, %f2
346         camellia_f      %f20, %f2, %f0, %f2
347         camellia_f      %f22, %f0, %f2, %f0
348
349         bge,pn          %icc, .L256key
350         nop
351         std     %f0, [$out + 0x10]      ! k[ 4,  5]
352         std     %f2, [$out + 0x18]      ! k[ 6,  7]
353
354         movdtox %f0, %o4
355         movdtox %f2, %o5
356         `&ROTL128(15)`
357         stx     %o4, [$out + 0x30]      ! k[12, 13]
358         stx     %o5, [$out + 0x38]      ! k[14, 15]
359         `&ROTL128(15)`
360         stx     %o4, [$out + 0x40]      ! k[16, 17]
361         stx     %o5, [$out + 0x48]      ! k[18, 19]
362         `&ROTL128(15)`
363         stx     %o4, [$out + 0x60]      ! k[24, 25]
364         `&ROTL128(15)`
365         stx     %o4, [$out + 0x70]      ! k[28, 29]
366         stx     %o5, [$out + 0x78]      ! k[30, 31]
367         `&ROTL128(34)`
368         stx     %o4, [$out + 0xa0]      ! k[40, 41]
369         stx     %o5, [$out + 0xa8]      ! k[42, 43]
370         `&ROTL128(17)`
371         stx     %o4, [$out + 0xc0]      ! k[48, 49]
372         stx     %o5, [$out + 0xc8]      ! k[50, 51]
373
374         movdtox %f28, %o4               ! k[ 0,  1]
375         movdtox %f30, %o5               ! k[ 2,  3]
376         `&ROTL128(15)`
377         stx     %o4, [$out + 0x20]      ! k[ 8,  9]
378         stx     %o5, [$out + 0x28]      ! k[10, 11]
379         `&ROTL128(30)`
380         stx     %o4, [$out + 0x50]      ! k[20, 21]
381         stx     %o5, [$out + 0x58]      ! k[22, 23]
382         `&ROTL128(15)`
383         stx     %o5, [$out + 0x68]      ! k[26, 27]
384         `&ROTL128(17)`
385         stx     %o4, [$out + 0x80]      ! k[32, 33]
386         stx     %o5, [$out + 0x88]      ! k[34, 35]
387         `&ROTL128(17)`
388         stx     %o4, [$out + 0x90]      ! k[36, 37]
389         stx     %o5, [$out + 0x98]      ! k[38, 39]
390         `&ROTL128(17)`
391         stx     %o4, [$out + 0xb0]      ! k[44, 45]
392         stx     %o5, [$out + 0xb8]      ! k[46, 47]
393
394         mov             3, $tmp
395         st              $tmp, [$out + 0x110]
396         retl
397         xor             %o0, %o0, %o0
398
399 .align  16
400 .L256key:
401         ldd             [%o4 + 32], %f24
402         ldd             [%o4 + 40], %f26
403
404         std             %f0, [$out + 0x30]      ! k[12, 13]
405         std             %f2, [$out + 0x38]      ! k[14, 15]
406
407         fxor            %f4, %f0, %f0
408         fxor            %f6, %f2, %f2
409         camellia_f      %f24, %f2, %f0, %f2
410         camellia_f      %f26, %f0, %f2, %f0
411
412         std     %f0, [$out + 0x10]      ! k[ 4,  5]
413         std     %f2, [$out + 0x18]      ! k[ 6,  7]
414
415         movdtox %f0, %o4
416         movdtox %f2, %o5
417         `&ROTL128(30)`
418         stx     %o4, [$out + 0x50]      ! k[20, 21]
419         stx     %o5, [$out + 0x58]      ! k[22, 23]
420         `&ROTL128(30)`
421         stx     %o4, [$out + 0xa0]      ! k[40, 41]
422         stx     %o5, [$out + 0xa8]      ! k[42, 43]
423         `&ROTL128(51)`
424         stx     %o4, [$out + 0x100]     ! k[64, 65]
425         stx     %o5, [$out + 0x108]     ! k[66, 67]
426
427         movdtox %f4, %o4                ! k[ 8,  9]
428         movdtox %f6, %o5                ! k[10, 11]
429         `&ROTL128(15)`
430         stx     %o4, [$out + 0x20]      ! k[ 8,  9]
431         stx     %o5, [$out + 0x28]      ! k[10, 11]
432         `&ROTL128(15)`
433         stx     %o4, [$out + 0x40]      ! k[16, 17]
434         stx     %o5, [$out + 0x48]      ! k[18, 19]
435         `&ROTL128(30)`
436         stx     %o4, [$out + 0x90]      ! k[36, 37]
437         stx     %o5, [$out + 0x98]      ! k[38, 39]
438         `&ROTL128(34)`
439         stx     %o4, [$out + 0xd0]      ! k[52, 53]
440         stx     %o5, [$out + 0xd8]      ! k[54, 55]
441         ldx     [$out + 0x30], %o4      ! k[12, 13]
442         ldx     [$out + 0x38], %o5      ! k[14, 15]
443         `&ROTL128(15)`
444         stx     %o4, [$out + 0x30]      ! k[12, 13]
445         stx     %o5, [$out + 0x38]      ! k[14, 15]
446         `&ROTL128(30)`
447         stx     %o4, [$out + 0x70]      ! k[28, 29]
448         stx     %o5, [$out + 0x78]      ! k[30, 31]
449         srlx    %o4, 32, %g4
450         srlx    %o5, 32, %g5
451         st      %o4, [$out + 0xc0]      ! k[48]
452         st      %g5, [$out + 0xc4]      ! k[49]
453         st      %o5, [$out + 0xc8]      ! k[50]
454         st      %g4, [$out + 0xcc]      ! k[51]
455         `&ROTL128(49)`
456         stx     %o4, [$out + 0xe0]      ! k[56, 57]
457         stx     %o5, [$out + 0xe8]      ! k[58, 59]
458
459         movdtox %f28, %o4               ! k[ 0,  1]
460         movdtox %f30, %o5               ! k[ 2,  3]
461         `&ROTL128(45)`
462         stx     %o4, [$out + 0x60]      ! k[24, 25]
463         stx     %o5, [$out + 0x68]      ! k[26, 27]
464         `&ROTL128(15)`
465         stx     %o4, [$out + 0x80]      ! k[32, 33]
466         stx     %o5, [$out + 0x88]      ! k[34, 35]
467         `&ROTL128(17)`
468         stx     %o4, [$out + 0xb0]      ! k[44, 45]
469         stx     %o5, [$out + 0xb8]      ! k[46, 47]
470         `&ROTL128(34)`
471         stx     %o4, [$out + 0xf0]      ! k[60, 61]
472         stx     %o5, [$out + 0xf8]      ! k[62, 63]
473
474         mov             4, $tmp
475         st              $tmp, [$out + 0x110]
476         retl
477         xor             %o0, %o0, %o0
478 .type   cmll_t4_set_key,#function
479 .size   cmll_t4_set_key,.-cmll_t4_set_key
480 .align  32
481 SIGMA:
482         .long   0xa09e667f, 0x3bcc908b, 0xb67ae858, 0x4caa73b2
483         .long   0xc6ef372f, 0xe94f82be, 0x54ff53a5, 0xf1d36f1c
484         .long   0x10e527fa, 0xde682d1d, 0xb05688c2, 0xb3e6c1fd
485 .type   SIGMA,#object
486 .size   SIGMA,.-SIGMA
487 .asciz  "Camellia for SPARC T4, David S. Miller, Andy Polyakov"
488 ___
489 }
490
491 {{{
492 my ($inp,$out,$len,$key,$ivec,$enc)=map("%i$_",(0..5));
493 my ($ileft,$iright,$ooff,$omask,$ivoff)=map("%l$_",(1..7));
494
495 $code.=<<___;
496 .align  32
497 _cmll128_load_enckey:
498         ldx             [$key + 0], %g4
499         ldx             [$key + 8], %g5
500 ___
501 for ($i=2; $i<26;$i++) {                        # load key schedule
502     $code.=<<___;
503         ldd             [$key + `8*$i`], %f`12+2*$i`
504 ___
505 }
506 $code.=<<___;
507         retl
508         nop
509 .type   _cmll128_load_enckey,#function
510 .size   _cmll128_load_enckey,.-_cmll128_load_enckey
511 _cmll256_load_enckey=_cmll128_load_enckey
512
513 .align  32
514 _cmll256_load_deckey:
515         ldd             [$key + 64], %f62
516         ldd             [$key + 72], %f60
517         b               .Load_deckey
518         add             $key, 64, $key
519 _cmll128_load_deckey:
520         ldd             [$key + 0], %f60
521         ldd             [$key + 8], %f62
522 .Load_deckey:
523 ___
524 for ($i=2; $i<24;$i++) {                        # load key schedule
525     $code.=<<___;
526         ldd             [$key + `8*$i`], %f`62-2*$i`
527 ___
528 }
529 $code.=<<___;
530         ldx             [$key + 192], %g4
531         retl
532         ldx             [$key + 200], %g5
533 .type   _cmll256_load_deckey,#function
534 .size   _cmll256_load_deckey,.-_cmll256_load_deckey
535
536 .align  32
537 _cmll128_encrypt_1x:
538 ___
539 for ($i=0; $i<3; $i++) {
540     $code.=<<___;
541         camellia_f      %f`16+16*$i+0`, %f2, %f0, %f2
542         camellia_f      %f`16+16*$i+2`, %f0, %f2, %f0
543         camellia_f      %f`16+16*$i+4`, %f2, %f0, %f2
544         camellia_f      %f`16+16*$i+6`, %f0, %f2, %f0
545 ___
546 $code.=<<___ if ($i<2);
547         camellia_f      %f`16+16*$i+8`, %f2, %f0, %f2
548         camellia_f      %f`16+16*$i+10`, %f0, %f2, %f0
549         camellia_fl     %f`16+16*$i+12`, %f0,      %f0
550         camellia_fli    %f`16+16*$i+14`, %f2,      %f2
551 ___
552 }
553 $code.=<<___;
554         camellia_f      %f56, %f2, %f0, %f4
555         camellia_f      %f58, %f0, %f4, %f2
556         fxor            %f60, %f4, %f0
557         retl
558         fxor            %f62, %f2, %f2
559 .type   _cmll128_encrypt_1x,#function
560 .size   _cmll128_encrypt_1x,.-_cmll128_encrypt_1x
561 _cmll128_decrypt_1x=_cmll128_encrypt_1x
562
563 .align  32
564 _cmll128_encrypt_2x:
565 ___
566 for ($i=0; $i<3; $i++) {
567     $code.=<<___;
568         camellia_f      %f`16+16*$i+0`, %f2, %f0, %f2
569         camellia_f      %f`16+16*$i+0`, %f6, %f4, %f6
570         camellia_f      %f`16+16*$i+2`, %f0, %f2, %f0
571         camellia_f      %f`16+16*$i+2`, %f4, %f6, %f4
572         camellia_f      %f`16+16*$i+4`, %f2, %f0, %f2
573         camellia_f      %f`16+16*$i+4`, %f6, %f4, %f6
574         camellia_f      %f`16+16*$i+6`, %f0, %f2, %f0
575         camellia_f      %f`16+16*$i+6`, %f4, %f6, %f4
576 ___
577 $code.=<<___ if ($i<2);
578         camellia_f      %f`16+16*$i+8`, %f2, %f0, %f2
579         camellia_f      %f`16+16*$i+8`, %f6, %f4, %f6
580         camellia_f      %f`16+16*$i+10`, %f0, %f2, %f0
581         camellia_f      %f`16+16*$i+10`, %f4, %f6, %f4
582         camellia_fl     %f`16+16*$i+12`, %f0,      %f0
583         camellia_fl     %f`16+16*$i+12`, %f4,      %f4
584         camellia_fli    %f`16+16*$i+14`, %f2,      %f2
585         camellia_fli    %f`16+16*$i+14`, %f6,      %f6
586 ___
587 }
588 $code.=<<___;
589         camellia_f      %f56, %f2, %f0, %f8
590         camellia_f      %f56, %f6, %f4, %f10
591         camellia_f      %f58, %f0, %f8, %f2
592         camellia_f      %f58, %f4, %f10, %f6
593         fxor            %f60, %f8, %f0
594         fxor            %f60, %f10, %f4
595         fxor            %f62, %f2, %f2
596         retl
597         fxor            %f62, %f6, %f6
598 .type   _cmll128_encrypt_2x,#function
599 .size   _cmll128_encrypt_2x,.-_cmll128_encrypt_2x
600 _cmll128_decrypt_2x=_cmll128_encrypt_2x
601
602 .align  32
603 _cmll256_encrypt_1x:
604         camellia_f      %f16, %f2, %f0, %f2
605         camellia_f      %f18, %f0, %f2, %f0
606         ldd             [$key + 208], %f16
607         ldd             [$key + 216], %f18
608         camellia_f      %f20, %f2, %f0, %f2
609         camellia_f      %f22, %f0, %f2, %f0
610         ldd             [$key + 224], %f20
611         ldd             [$key + 232], %f22
612         camellia_f      %f24, %f2, %f0, %f2
613         camellia_f      %f26, %f0, %f2, %f0
614         ldd             [$key + 240], %f24
615         ldd             [$key + 248], %f26
616         camellia_fl     %f28, %f0, %f0
617         camellia_fli    %f30, %f2, %f2
618         ldd             [$key + 256], %f28
619         ldd             [$key + 264], %f30
620 ___
621 for ($i=1; $i<3; $i++) {
622     $code.=<<___;
623         camellia_f      %f`16+16*$i+0`, %f2, %f0, %f2
624         camellia_f      %f`16+16*$i+2`, %f0, %f2, %f0
625         camellia_f      %f`16+16*$i+4`, %f2, %f0, %f2
626         camellia_f      %f`16+16*$i+6`, %f0, %f2, %f0
627         camellia_f      %f`16+16*$i+8`, %f2, %f0, %f2
628         camellia_f      %f`16+16*$i+10`, %f0, %f2, %f0
629         camellia_fl     %f`16+16*$i+12`, %f0,      %f0
630         camellia_fli    %f`16+16*$i+14`, %f2,      %f2
631 ___
632 }
633 $code.=<<___;
634         camellia_f      %f16, %f2, %f0, %f2
635         camellia_f      %f18, %f0, %f2, %f0
636         ldd             [$key + 16], %f16
637         ldd             [$key + 24], %f18
638         camellia_f      %f20, %f2, %f0, %f2
639         camellia_f      %f22, %f0, %f2, %f0
640         ldd             [$key + 32], %f20
641         ldd             [$key + 40], %f22
642         camellia_f      %f24, %f2, %f0, %f4
643         camellia_f      %f26, %f0, %f4, %f2
644         ldd             [$key + 48], %f24
645         ldd             [$key + 56], %f26
646         fxor            %f28, %f4, %f0
647         fxor            %f30, %f2, %f2
648         ldd             [$key + 64], %f28
649         retl
650         ldd             [$key + 72], %f30
651 .type   _cmll256_encrypt_1x,#function
652 .size   _cmll256_encrypt_1x,.-_cmll256_encrypt_1x
653
654 .align  32
655 _cmll256_encrypt_2x:
656         camellia_f      %f16, %f2, %f0, %f2
657         camellia_f      %f16, %f6, %f4, %f6
658         camellia_f      %f18, %f0, %f2, %f0
659         camellia_f      %f18, %f4, %f6, %f4
660         ldd             [$key + 208], %f16
661         ldd             [$key + 216], %f18
662         camellia_f      %f20, %f2, %f0, %f2
663         camellia_f      %f20, %f6, %f4, %f6
664         camellia_f      %f22, %f0, %f2, %f0
665         camellia_f      %f22, %f4, %f6, %f4
666         ldd             [$key + 224], %f20
667         ldd             [$key + 232], %f22
668         camellia_f      %f24, %f2, %f0, %f2
669         camellia_f      %f24, %f6, %f4, %f6
670         camellia_f      %f26, %f0, %f2, %f0
671         camellia_f      %f26, %f4, %f6, %f4
672         ldd             [$key + 240], %f24
673         ldd             [$key + 248], %f26
674         camellia_fl     %f28, %f0, %f0
675         camellia_fl     %f28, %f4, %f4
676         camellia_fli    %f30, %f2, %f2
677         camellia_fli    %f30, %f6, %f6
678         ldd             [$key + 256], %f28
679         ldd             [$key + 264], %f30
680 ___
681 for ($i=1; $i<3; $i++) {
682     $code.=<<___;
683         camellia_f      %f`16+16*$i+0`, %f2, %f0, %f2
684         camellia_f      %f`16+16*$i+0`, %f6, %f4, %f6
685         camellia_f      %f`16+16*$i+2`, %f0, %f2, %f0
686         camellia_f      %f`16+16*$i+2`, %f4, %f6, %f4
687         camellia_f      %f`16+16*$i+4`, %f2, %f0, %f2
688         camellia_f      %f`16+16*$i+4`, %f6, %f4, %f6
689         camellia_f      %f`16+16*$i+6`, %f0, %f2, %f0
690         camellia_f      %f`16+16*$i+6`, %f4, %f6, %f4
691         camellia_f      %f`16+16*$i+8`, %f2, %f0, %f2
692         camellia_f      %f`16+16*$i+8`, %f6, %f4, %f6
693         camellia_f      %f`16+16*$i+10`, %f0, %f2, %f0
694         camellia_f      %f`16+16*$i+10`, %f4, %f6, %f4
695         camellia_fl     %f`16+16*$i+12`, %f0,      %f0
696         camellia_fl     %f`16+16*$i+12`, %f4,      %f4
697         camellia_fli    %f`16+16*$i+14`, %f2,      %f2
698         camellia_fli    %f`16+16*$i+14`, %f6,      %f6
699 ___
700 }
701 $code.=<<___;
702         camellia_f      %f16, %f2, %f0, %f2
703         camellia_f      %f16, %f6, %f4, %f6
704         camellia_f      %f18, %f0, %f2, %f0
705         camellia_f      %f18, %f4, %f6, %f4
706         ldd             [$key + 16], %f16
707         ldd             [$key + 24], %f18
708         camellia_f      %f20, %f2, %f0, %f2
709         camellia_f      %f20, %f6, %f4, %f6
710         camellia_f      %f22, %f0, %f2, %f0
711         camellia_f      %f22, %f4, %f6, %f4
712         ldd             [$key + 32], %f20
713         ldd             [$key + 40], %f22
714         camellia_f      %f24, %f2, %f0, %f8
715         camellia_f      %f24, %f6, %f4, %f10
716         camellia_f      %f26, %f0, %f8, %f2
717         camellia_f      %f26, %f4, %f10, %f6
718         ldd             [$key + 48], %f24
719         ldd             [$key + 56], %f26
720         fxor            %f28, %f8, %f0
721         fxor            %f28, %f10, %f4
722         fxor            %f30, %f2, %f2
723         fxor            %f30, %f6, %f6
724         ldd             [$key + 64], %f28
725         retl
726         ldd             [$key + 72], %f30
727 .type   _cmll256_encrypt_2x,#function
728 .size   _cmll256_encrypt_2x,.-_cmll256_encrypt_2x
729
730 .align  32
731 _cmll256_decrypt_1x:
732         camellia_f      %f16, %f2, %f0, %f2
733         camellia_f      %f18, %f0, %f2, %f0
734         ldd             [$key - 8], %f16
735         ldd             [$key - 16], %f18
736         camellia_f      %f20, %f2, %f0, %f2
737         camellia_f      %f22, %f0, %f2, %f0
738         ldd             [$key - 24], %f20
739         ldd             [$key - 32], %f22
740         camellia_f      %f24, %f2, %f0, %f2
741         camellia_f      %f26, %f0, %f2, %f0
742         ldd             [$key - 40], %f24
743         ldd             [$key - 48], %f26
744         camellia_fl     %f28, %f0, %f0
745         camellia_fli    %f30, %f2, %f2
746         ldd             [$key - 56], %f28
747         ldd             [$key - 64], %f30
748 ___
749 for ($i=1; $i<3; $i++) {
750     $code.=<<___;
751         camellia_f      %f`16+16*$i+0`, %f2, %f0, %f2
752         camellia_f      %f`16+16*$i+2`, %f0, %f2, %f0
753         camellia_f      %f`16+16*$i+4`, %f2, %f0, %f2
754         camellia_f      %f`16+16*$i+6`, %f0, %f2, %f0
755         camellia_f      %f`16+16*$i+8`, %f2, %f0, %f2
756         camellia_f      %f`16+16*$i+10`, %f0, %f2, %f0
757         camellia_fl     %f`16+16*$i+12`, %f0,      %f0
758         camellia_fli    %f`16+16*$i+14`, %f2,      %f2
759 ___
760 }
761 $code.=<<___;
762         camellia_f      %f16, %f2, %f0, %f2
763         camellia_f      %f18, %f0, %f2, %f0
764         ldd             [$key + 184], %f16
765         ldd             [$key + 176], %f18
766         camellia_f      %f20, %f2, %f0, %f2
767         camellia_f      %f22, %f0, %f2, %f0
768         ldd             [$key + 168], %f20
769         ldd             [$key + 160], %f22
770         camellia_f      %f24, %f2, %f0, %f4
771         camellia_f      %f26, %f0, %f4, %f2
772         ldd             [$key + 152], %f24
773         ldd             [$key + 144], %f26
774         fxor            %f30, %f4, %f0
775         fxor            %f28, %f2, %f2
776         ldd             [$key + 136], %f28
777         retl
778         ldd             [$key + 128], %f30
779 .type   _cmll256_decrypt_1x,#function
780 .size   _cmll256_decrypt_1x,.-_cmll256_decrypt_1x
781
782 .align  32
783 _cmll256_decrypt_2x:
784         camellia_f      %f16, %f2, %f0, %f2
785         camellia_f      %f16, %f6, %f4, %f6
786         camellia_f      %f18, %f0, %f2, %f0
787         camellia_f      %f18, %f4, %f6, %f4
788         ldd             [$key - 8], %f16
789         ldd             [$key - 16], %f18
790         camellia_f      %f20, %f2, %f0, %f2
791         camellia_f      %f20, %f6, %f4, %f6
792         camellia_f      %f22, %f0, %f2, %f0
793         camellia_f      %f22, %f4, %f6, %f4
794         ldd             [$key - 24], %f20
795         ldd             [$key - 32], %f22
796         camellia_f      %f24, %f2, %f0, %f2
797         camellia_f      %f24, %f6, %f4, %f6
798         camellia_f      %f26, %f0, %f2, %f0
799         camellia_f      %f26, %f4, %f6, %f4
800         ldd             [$key - 40], %f24
801         ldd             [$key - 48], %f26
802         camellia_fl     %f28, %f0, %f0
803         camellia_fl     %f28, %f4, %f4
804         camellia_fli    %f30, %f2, %f2
805         camellia_fli    %f30, %f6, %f6
806         ldd             [$key - 56], %f28
807         ldd             [$key - 64], %f30
808 ___
809 for ($i=1; $i<3; $i++) {
810     $code.=<<___;
811         camellia_f      %f`16+16*$i+0`, %f2, %f0, %f2
812         camellia_f      %f`16+16*$i+0`, %f6, %f4, %f6
813         camellia_f      %f`16+16*$i+2`, %f0, %f2, %f0
814         camellia_f      %f`16+16*$i+2`, %f4, %f6, %f4
815         camellia_f      %f`16+16*$i+4`, %f2, %f0, %f2
816         camellia_f      %f`16+16*$i+4`, %f6, %f4, %f6
817         camellia_f      %f`16+16*$i+6`, %f0, %f2, %f0
818         camellia_f      %f`16+16*$i+6`, %f4, %f6, %f4
819         camellia_f      %f`16+16*$i+8`, %f2, %f0, %f2
820         camellia_f      %f`16+16*$i+8`, %f6, %f4, %f6
821         camellia_f      %f`16+16*$i+10`, %f0, %f2, %f0
822         camellia_f      %f`16+16*$i+10`, %f4, %f6, %f4
823         camellia_fl     %f`16+16*$i+12`, %f0,      %f0
824         camellia_fl     %f`16+16*$i+12`, %f4,      %f4
825         camellia_fli    %f`16+16*$i+14`, %f2,      %f2
826         camellia_fli    %f`16+16*$i+14`, %f6,      %f6
827 ___
828 }
829 $code.=<<___;
830         camellia_f      %f16, %f2, %f0, %f2
831         camellia_f      %f16, %f6, %f4, %f6
832         camellia_f      %f18, %f0, %f2, %f0
833         camellia_f      %f18, %f4, %f6, %f4
834         ldd             [$key + 184], %f16
835         ldd             [$key + 176], %f18
836         camellia_f      %f20, %f2, %f0, %f2
837         camellia_f      %f20, %f6, %f4, %f6
838         camellia_f      %f22, %f0, %f2, %f0
839         camellia_f      %f22, %f4, %f6, %f4
840         ldd             [$key + 168], %f20
841         ldd             [$key + 160], %f22
842         camellia_f      %f24, %f2, %f0, %f8
843         camellia_f      %f24, %f6, %f4, %f10
844         camellia_f      %f26, %f0, %f8, %f2
845         camellia_f      %f26, %f4, %f10, %f6
846         ldd             [$key + 152], %f24
847         ldd             [$key + 144], %f26
848         fxor            %f30, %f8, %f0
849         fxor            %f30, %f10, %f4
850         fxor            %f28, %f2, %f2
851         fxor            %f28, %f6, %f6
852         ldd             [$key + 136], %f28
853         retl
854         ldd             [$key + 128], %f30
855 .type   _cmll256_decrypt_2x,#function
856 .size   _cmll256_decrypt_2x,.-_cmll256_decrypt_2x
857 ___
858
859 &alg_cbc_encrypt_implement("cmll",128);
860 &alg_cbc_encrypt_implement("cmll",256);
861
862 &alg_cbc_decrypt_implement("cmll",128);
863 &alg_cbc_decrypt_implement("cmll",256);
864
865 if ($::evp) {
866     &alg_ctr32_implement("cmll",128);
867     &alg_ctr32_implement("cmll",256);
868 }
869 }}}
870
871 if (!$::evp) {
872 $code.=<<___;
873 .global Camellia_encrypt
874 Camellia_encrypt=cmll_t4_encrypt
875 .global Camellia_decrypt
876 Camellia_decrypt=cmll_t4_decrypt
877 .global Camellia_set_key
878 .align  32
879 Camellia_set_key:
880         andcc           %o2, 7, %g0             ! double-check alignment
881         bnz,a,pn        %icc, 1f
882         mov             -1, %o0
883         brz,a,pn        %o0, 1f
884         mov             -1, %o0
885         brz,a,pn        %o2, 1f
886         mov             -1, %o0
887         andncc          %o1, 0x1c0, %g0
888         bnz,a,pn        %icc, 1f
889         mov             -2, %o0
890         cmp             %o1, 128
891         bl,a,pn         %icc, 1f
892         mov             -2, %o0
893         b               cmll_t4_set_key
894         nop
895 1:      retl
896         nop
897 .type   Camellia_set_key,#function
898 .size   Camellia_set_key,.-Camellia_set_key
899 ___
900
901 my ($inp,$out,$len,$key,$ivec,$enc)=map("%o$_",(0..5));
902
903 $code.=<<___;
904 .globl  Camellia_cbc_encrypt
905 .align  32
906 Camellia_cbc_encrypt:
907         ld              [$key + 272], %g1
908         nop
909         brz             $enc, .Lcbc_decrypt
910         cmp             %g1, 3
911
912         be,pt           %icc, cmll128_t4_cbc_encrypt
913         nop
914         ba              cmll256_t4_cbc_encrypt
915         nop
916
917 .Lcbc_decrypt:
918         be,pt           %icc, cmll128_t4_cbc_decrypt
919         nop
920         ba              cmll256_t4_cbc_decrypt
921         nop
922 .type   Camellia_cbc_encrypt,#function
923 .size   Camellia_cbc_encrypt,.-Camellia_cbc_encrypt
924 ___
925 }
926
927 &emit_assembler();
928
929 close STDOUT;