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