Add X509_CHECK_FLAG_NEVER_CHECK_SUBJECT flag
[openssl.git] / crypto / perlasm / sparcv9_modes.pl
1 #!/usr/bin/env perl
2
3 # Specific modes implementations for SPARC Architecture 2011. There
4 # is T4 dependency though, an ASI value that is not specified in the
5 # Architecture Manual. But as SPARC universe is rather monocultural,
6 # we imply that processor capable of executing crypto instructions
7 # can handle the ASI in question as well. This means that we ought to
8 # keep eyes open when new processors emerge...
9 #
10 # As for above mentioned ASI. It's so called "block initializing
11 # store" which cancels "read" in "read-update-write" on cache lines.
12 # This is "cooperative" optimization, as it reduces overall pressure
13 # on memory interface. Benefits can't be observed/quantified with
14 # usual benchmarks, on the contrary you can notice that single-thread
15 # performance for parallelizable modes is ~1.5% worse for largest
16 # block sizes [though few percent better for not so long ones]. All
17 # this based on suggestions from David Miller.
18
19 $::bias="STACK_BIAS";
20 $::frame="STACK_FRAME";
21 $::size_t_cc="SIZE_T_CC";
22
23 sub asm_init {          # to be called with @ARGV as argument
24     for (@_)            { $::abibits=64 if (/\-m64/ || /\-xarch\=v9/); }
25     if ($::abibits==64) { $::bias=2047; $::frame=192; $::size_t_cc="%xcc"; }
26     else                { $::bias=0;    $::frame=112; $::size_t_cc="%icc"; }
27 }
28
29 # unified interface
30 my ($inp,$out,$len,$key,$ivec)=map("%i$_",(0..5));
31 # local variables
32 my ($ileft,$iright,$ooff,$omask,$ivoff,$blk_init)=map("%l$_",(0..7));
33
34 sub alg_cbc_encrypt_implement {
35 my ($alg,$bits) = @_;
36
37 $::code.=<<___;
38 .globl  ${alg}${bits}_t4_cbc_encrypt
39 .align  32
40 ${alg}${bits}_t4_cbc_encrypt:
41         save            %sp, -$::frame, %sp
42         cmp             $len, 0
43         be,pn           $::size_t_cc, .L${bits}_cbc_enc_abort
44         sub             $inp, $out, $blk_init   ! $inp!=$out
45 ___
46 $::code.=<<___ if (!$::evp);
47         andcc           $ivec, 7, $ivoff
48         alignaddr       $ivec, %g0, $ivec
49
50         ldd             [$ivec + 0], %f0        ! load ivec
51         bz,pt           %icc, 1f
52         ldd             [$ivec + 8], %f2
53         ldd             [$ivec + 16], %f4
54         faligndata      %f0, %f2, %f0
55         faligndata      %f2, %f4, %f2
56 1:
57 ___
58 $::code.=<<___ if ($::evp);
59         ld              [$ivec + 0], %f0
60         ld              [$ivec + 4], %f1
61         ld              [$ivec + 8], %f2
62         ld              [$ivec + 12], %f3
63 ___
64 $::code.=<<___;
65         prefetch        [$inp], 20
66         prefetch        [$inp + 63], 20
67         call            _${alg}${bits}_load_enckey
68         and             $inp, 7, $ileft
69         andn            $inp, 7, $inp
70         sll             $ileft, 3, $ileft
71         mov             64, $iright
72         mov             0xff, $omask
73         sub             $iright, $ileft, $iright
74         and             $out, 7, $ooff
75         cmp             $len, 127
76         movrnz          $ooff, 0, $blk_init             ! if (  $out&7 ||
77         movleu          $::size_t_cc, 0, $blk_init      !       $len<128 ||
78         brnz,pn         $blk_init, .L${bits}cbc_enc_blk !       $inp==$out)
79         srl             $omask, $ooff, $omask
80
81         alignaddrl      $out, %g0, $out
82         srlx            $len, 4, $len
83         prefetch        [$out], 22
84
85 .L${bits}_cbc_enc_loop:
86         ldx             [$inp + 0], %o0
87         brz,pt          $ileft, 4f
88         ldx             [$inp + 8], %o1
89
90         ldx             [$inp + 16], %o2
91         sllx            %o0, $ileft, %o0
92         srlx            %o1, $iright, %g1
93         sllx            %o1, $ileft, %o1
94         or              %g1, %o0, %o0
95         srlx            %o2, $iright, %o2
96         or              %o2, %o1, %o1
97 4:
98         xor             %g4, %o0, %o0           ! ^= rk[0]
99         xor             %g5, %o1, %o1
100         movxtod         %o0, %f12
101         movxtod         %o1, %f14
102
103         fxor            %f12, %f0, %f0          ! ^= ivec
104         fxor            %f14, %f2, %f2
105         prefetch        [$out + 63], 22
106         prefetch        [$inp + 16+63], 20
107         call            _${alg}${bits}_encrypt_1x
108         add             $inp, 16, $inp
109
110         brnz,pn         $ooff, 2f
111         sub             $len, 1, $len
112                 
113         std             %f0, [$out + 0]
114         std             %f2, [$out + 8]
115         brnz,pt         $len, .L${bits}_cbc_enc_loop
116         add             $out, 16, $out
117 ___
118 $::code.=<<___ if ($::evp);
119         st              %f0, [$ivec + 0]
120         st              %f1, [$ivec + 4]
121         st              %f2, [$ivec + 8]
122         st              %f3, [$ivec + 12]
123 ___
124 $::code.=<<___ if (!$::evp);
125         brnz,pn         $ivoff, 3f
126         nop
127
128         std             %f0, [$ivec + 0]        ! write out ivec
129         std             %f2, [$ivec + 8]
130 ___
131 $::code.=<<___;
132 .L${bits}_cbc_enc_abort:
133         ret
134         restore
135
136 .align  16
137 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
138                                                 ! and ~3x deterioration
139                                                 ! in inp==out case
140         faligndata      %f0, %f0, %f4           ! handle unaligned output
141         faligndata      %f0, %f2, %f6
142         faligndata      %f2, %f2, %f8
143
144         stda            %f4, [$out + $omask]0xc0        ! partial store
145         std             %f6, [$out + 8]
146         add             $out, 16, $out
147         orn             %g0, $omask, $omask
148         stda            %f8, [$out + $omask]0xc0        ! partial store
149
150         brnz,pt         $len, .L${bits}_cbc_enc_loop+4
151         orn             %g0, $omask, $omask
152 ___
153 $::code.=<<___ if ($::evp);
154         st              %f0, [$ivec + 0]
155         st              %f1, [$ivec + 4]
156         st              %f2, [$ivec + 8]
157         st              %f3, [$ivec + 12]
158 ___
159 $::code.=<<___ if (!$::evp);
160         brnz,pn         $ivoff, 3f
161         nop
162
163         std             %f0, [$ivec + 0]        ! write out ivec
164         std             %f2, [$ivec + 8]
165         ret
166         restore
167
168 .align  16
169 3:      alignaddrl      $ivec, $ivoff, %g0      ! handle unaligned ivec
170         mov             0xff, $omask
171         srl             $omask, $ivoff, $omask
172         faligndata      %f0, %f0, %f4
173         faligndata      %f0, %f2, %f6
174         faligndata      %f2, %f2, %f8
175         stda            %f4, [$ivec + $omask]0xc0
176         std             %f6, [$ivec + 8]
177         add             $ivec, 16, $ivec
178         orn             %g0, $omask, $omask
179         stda            %f8, [$ivec + $omask]0xc0
180 ___
181 $::code.=<<___;
182         ret
183         restore
184
185 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
186 .align  32
187 .L${bits}cbc_enc_blk:
188         add     $out, $len, $blk_init
189         and     $blk_init, 63, $blk_init        ! tail
190         sub     $len, $blk_init, $len
191         add     $blk_init, 15, $blk_init        ! round up to 16n
192         srlx    $len, 4, $len
193         srl     $blk_init, 4, $blk_init
194
195 .L${bits}_cbc_enc_blk_loop:
196         ldx             [$inp + 0], %o0
197         brz,pt          $ileft, 5f
198         ldx             [$inp + 8], %o1
199
200         ldx             [$inp + 16], %o2
201         sllx            %o0, $ileft, %o0
202         srlx            %o1, $iright, %g1
203         sllx            %o1, $ileft, %o1
204         or              %g1, %o0, %o0
205         srlx            %o2, $iright, %o2
206         or              %o2, %o1, %o1
207 5:
208         xor             %g4, %o0, %o0           ! ^= rk[0]
209         xor             %g5, %o1, %o1
210         movxtod         %o0, %f12
211         movxtod         %o1, %f14
212
213         fxor            %f12, %f0, %f0          ! ^= ivec
214         fxor            %f14, %f2, %f2
215         prefetch        [$inp + 16+63], 20
216         call            _${alg}${bits}_encrypt_1x
217         add             $inp, 16, $inp
218         sub             $len, 1, $len
219                 
220         stda            %f0, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
221         add             $out, 8, $out
222         stda            %f2, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
223         brnz,pt         $len, .L${bits}_cbc_enc_blk_loop
224         add             $out, 8, $out
225
226         membar          #StoreLoad|#StoreStore
227         brnz,pt         $blk_init, .L${bits}_cbc_enc_loop
228         mov             $blk_init, $len
229 ___
230 $::code.=<<___ if ($::evp);
231         st              %f0, [$ivec + 0]
232         st              %f1, [$ivec + 4]
233         st              %f2, [$ivec + 8]
234         st              %f3, [$ivec + 12]
235 ___
236 $::code.=<<___ if (!$::evp);
237         brnz,pn         $ivoff, 3b
238         nop
239
240         std             %f0, [$ivec + 0]        ! write out ivec
241         std             %f2, [$ivec + 8]
242 ___
243 $::code.=<<___;
244         ret
245         restore
246 .type   ${alg}${bits}_t4_cbc_encrypt,#function
247 .size   ${alg}${bits}_t4_cbc_encrypt,.-${alg}${bits}_t4_cbc_encrypt
248 ___
249 }
250
251 sub alg_cbc_decrypt_implement {
252 my ($alg,$bits) = @_;
253
254 $::code.=<<___;
255 .globl  ${alg}${bits}_t4_cbc_decrypt
256 .align  32
257 ${alg}${bits}_t4_cbc_decrypt:
258         save            %sp, -$::frame, %sp
259         cmp             $len, 0
260         be,pn           $::size_t_cc, .L${bits}_cbc_dec_abort
261         sub             $inp, $out, $blk_init   ! $inp!=$out
262 ___
263 $::code.=<<___ if (!$::evp);
264         andcc           $ivec, 7, $ivoff
265         alignaddr       $ivec, %g0, $ivec
266
267         ldd             [$ivec + 0], %f12       ! load ivec
268         bz,pt           %icc, 1f
269         ldd             [$ivec + 8], %f14
270         ldd             [$ivec + 16], %f0
271         faligndata      %f12, %f14, %f12
272         faligndata      %f14, %f0, %f14
273 1:
274 ___
275 $::code.=<<___ if ($::evp);
276         ld              [$ivec + 0], %f12       ! load ivec
277         ld              [$ivec + 4], %f13
278         ld              [$ivec + 8], %f14
279         ld              [$ivec + 12], %f15
280 ___
281 $::code.=<<___;
282         prefetch        [$inp], 20
283         prefetch        [$inp + 63], 20
284         call            _${alg}${bits}_load_deckey
285         and             $inp, 7, $ileft
286         andn            $inp, 7, $inp
287         sll             $ileft, 3, $ileft
288         mov             64, $iright
289         mov             0xff, $omask
290         sub             $iright, $ileft, $iright
291         and             $out, 7, $ooff
292         cmp             $len, 255
293         movrnz          $ooff, 0, $blk_init             ! if (  $out&7 ||
294         movleu          $::size_t_cc, 0, $blk_init      !       $len<256 ||
295         brnz,pn         $blk_init, .L${bits}cbc_dec_blk !       $inp==$out)
296         srl             $omask, $ooff, $omask
297
298         andcc           $len, 16, %g0           ! is number of blocks even?
299         srlx            $len, 4, $len
300         alignaddrl      $out, %g0, $out
301         bz              %icc, .L${bits}_cbc_dec_loop2x
302         prefetch        [$out], 22
303 .L${bits}_cbc_dec_loop:
304         ldx             [$inp + 0], %o0
305         brz,pt          $ileft, 4f
306         ldx             [$inp + 8], %o1
307
308         ldx             [$inp + 16], %o2
309         sllx            %o0, $ileft, %o0
310         srlx            %o1, $iright, %g1
311         sllx            %o1, $ileft, %o1
312         or              %g1, %o0, %o0
313         srlx            %o2, $iright, %o2
314         or              %o2, %o1, %o1
315 4:
316         xor             %g4, %o0, %o2           ! ^= rk[0]
317         xor             %g5, %o1, %o3
318         movxtod         %o2, %f0
319         movxtod         %o3, %f2
320
321         prefetch        [$out + 63], 22
322         prefetch        [$inp + 16+63], 20
323         call            _${alg}${bits}_decrypt_1x
324         add             $inp, 16, $inp
325
326         fxor            %f12, %f0, %f0          ! ^= ivec
327         fxor            %f14, %f2, %f2
328         movxtod         %o0, %f12
329         movxtod         %o1, %f14
330
331         brnz,pn         $ooff, 2f
332         sub             $len, 1, $len
333                 
334         std             %f0, [$out + 0]
335         std             %f2, [$out + 8]
336         brnz,pt         $len, .L${bits}_cbc_dec_loop2x
337         add             $out, 16, $out
338 ___
339 $::code.=<<___ if ($::evp);
340         st              %f12, [$ivec + 0]
341         st              %f13, [$ivec + 4]
342         st              %f14, [$ivec + 8]
343         st              %f15, [$ivec + 12]
344 ___
345 $::code.=<<___ if (!$::evp);
346         brnz,pn         $ivoff, .L${bits}_cbc_dec_unaligned_ivec
347         nop
348
349         std             %f12, [$ivec + 0]       ! write out ivec
350         std             %f14, [$ivec + 8]
351 ___
352 $::code.=<<___;
353 .L${bits}_cbc_dec_abort:
354         ret
355         restore
356
357 .align  16
358 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
359                                                 ! and ~3x deterioration
360                                                 ! in inp==out case
361         faligndata      %f0, %f0, %f4           ! handle unaligned output
362         faligndata      %f0, %f2, %f6
363         faligndata      %f2, %f2, %f8
364
365         stda            %f4, [$out + $omask]0xc0        ! partial store
366         std             %f6, [$out + 8]
367         add             $out, 16, $out
368         orn             %g0, $omask, $omask
369         stda            %f8, [$out + $omask]0xc0        ! partial store
370
371         brnz,pt         $len, .L${bits}_cbc_dec_loop2x+4
372         orn             %g0, $omask, $omask
373 ___
374 $::code.=<<___ if ($::evp);
375         st              %f12, [$ivec + 0]
376         st              %f13, [$ivec + 4]
377         st              %f14, [$ivec + 8]
378         st              %f15, [$ivec + 12]
379 ___
380 $::code.=<<___ if (!$::evp);
381         brnz,pn         $ivoff, .L${bits}_cbc_dec_unaligned_ivec
382         nop
383
384         std             %f12, [$ivec + 0]       ! write out ivec
385         std             %f14, [$ivec + 8]
386 ___
387 $::code.=<<___;
388         ret
389         restore
390
391 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
392 .align  32
393 .L${bits}_cbc_dec_loop2x:
394         ldx             [$inp + 0], %o0
395         ldx             [$inp + 8], %o1
396         ldx             [$inp + 16], %o2
397         brz,pt          $ileft, 4f
398         ldx             [$inp + 24], %o3
399
400         ldx             [$inp + 32], %o4
401         sllx            %o0, $ileft, %o0
402         srlx            %o1, $iright, %g1
403         or              %g1, %o0, %o0
404         sllx            %o1, $ileft, %o1
405         srlx            %o2, $iright, %g1
406         or              %g1, %o1, %o1
407         sllx            %o2, $ileft, %o2
408         srlx            %o3, $iright, %g1
409         or              %g1, %o2, %o2
410         sllx            %o3, $ileft, %o3
411         srlx            %o4, $iright, %o4
412         or              %o4, %o3, %o3
413 4:
414         xor             %g4, %o0, %o4           ! ^= rk[0]
415         xor             %g5, %o1, %o5
416         movxtod         %o4, %f0
417         movxtod         %o5, %f2
418         xor             %g4, %o2, %o4
419         xor             %g5, %o3, %o5
420         movxtod         %o4, %f4
421         movxtod         %o5, %f6
422
423         prefetch        [$out + 63], 22
424         prefetch        [$inp + 32+63], 20
425         call            _${alg}${bits}_decrypt_2x
426         add             $inp, 32, $inp
427
428         movxtod         %o0, %f8
429         movxtod         %o1, %f10
430         fxor            %f12, %f0, %f0          ! ^= ivec
431         fxor            %f14, %f2, %f2
432         movxtod         %o2, %f12
433         movxtod         %o3, %f14
434         fxor            %f8, %f4, %f4
435         fxor            %f10, %f6, %f6
436
437         brnz,pn         $ooff, 2f
438         sub             $len, 2, $len
439                 
440         std             %f0, [$out + 0]
441         std             %f2, [$out + 8]
442         std             %f4, [$out + 16]
443         std             %f6, [$out + 24]
444         brnz,pt         $len, .L${bits}_cbc_dec_loop2x
445         add             $out, 32, $out
446 ___
447 $::code.=<<___ if ($::evp);
448         st              %f12, [$ivec + 0]
449         st              %f13, [$ivec + 4]
450         st              %f14, [$ivec + 8]
451         st              %f15, [$ivec + 12]
452 ___
453 $::code.=<<___ if (!$::evp);
454         brnz,pn         $ivoff, .L${bits}_cbc_dec_unaligned_ivec
455         nop
456
457         std             %f12, [$ivec + 0]       ! write out ivec
458         std             %f14, [$ivec + 8]
459 ___
460 $::code.=<<___;
461         ret
462         restore
463
464 .align  16
465 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
466                                                 ! and ~3x deterioration
467                                                 ! in inp==out case
468         faligndata      %f0, %f0, %f8           ! handle unaligned output
469         faligndata      %f0, %f2, %f0
470         faligndata      %f2, %f4, %f2
471         faligndata      %f4, %f6, %f4
472         faligndata      %f6, %f6, %f6
473         stda            %f8, [$out + $omask]0xc0        ! partial store
474         std             %f0, [$out + 8]
475         std             %f2, [$out + 16]
476         std             %f4, [$out + 24]
477         add             $out, 32, $out
478         orn             %g0, $omask, $omask
479         stda            %f6, [$out + $omask]0xc0        ! partial store
480
481         brnz,pt         $len, .L${bits}_cbc_dec_loop2x+4
482         orn             %g0, $omask, $omask
483 ___
484 $::code.=<<___ if ($::evp);
485         st              %f12, [$ivec + 0]
486         st              %f13, [$ivec + 4]
487         st              %f14, [$ivec + 8]
488         st              %f15, [$ivec + 12]
489 ___
490 $::code.=<<___ if (!$::evp);
491         brnz,pn         $ivoff, .L${bits}_cbc_dec_unaligned_ivec
492         nop
493
494         std             %f12, [$ivec + 0]       ! write out ivec
495         std             %f14, [$ivec + 8]
496         ret
497         restore
498
499 .align  16
500 .L${bits}_cbc_dec_unaligned_ivec:
501         alignaddrl      $ivec, $ivoff, %g0      ! handle unaligned ivec
502         mov             0xff, $omask
503         srl             $omask, $ivoff, $omask
504         faligndata      %f12, %f12, %f0
505         faligndata      %f12, %f14, %f2
506         faligndata      %f14, %f14, %f4
507         stda            %f0, [$ivec + $omask]0xc0
508         std             %f2, [$ivec + 8]
509         add             $ivec, 16, $ivec
510         orn             %g0, $omask, $omask
511         stda            %f4, [$ivec + $omask]0xc0
512 ___
513 $::code.=<<___;
514         ret
515         restore
516
517 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
518 .align  32
519 .L${bits}cbc_dec_blk:
520         add     $out, $len, $blk_init
521         and     $blk_init, 63, $blk_init        ! tail
522         sub     $len, $blk_init, $len
523         add     $blk_init, 15, $blk_init        ! round up to 16n
524         srlx    $len, 4, $len
525         srl     $blk_init, 4, $blk_init
526         sub     $len, 1, $len
527         add     $blk_init, 1, $blk_init
528
529 .L${bits}_cbc_dec_blk_loop2x:
530         ldx             [$inp + 0], %o0
531         ldx             [$inp + 8], %o1
532         ldx             [$inp + 16], %o2
533         brz,pt          $ileft, 5f
534         ldx             [$inp + 24], %o3
535
536         ldx             [$inp + 32], %o4
537         sllx            %o0, $ileft, %o0
538         srlx            %o1, $iright, %g1
539         or              %g1, %o0, %o0
540         sllx            %o1, $ileft, %o1
541         srlx            %o2, $iright, %g1
542         or              %g1, %o1, %o1
543         sllx            %o2, $ileft, %o2
544         srlx            %o3, $iright, %g1
545         or              %g1, %o2, %o2
546         sllx            %o3, $ileft, %o3
547         srlx            %o4, $iright, %o4
548         or              %o4, %o3, %o3
549 5:
550         xor             %g4, %o0, %o4           ! ^= rk[0]
551         xor             %g5, %o1, %o5
552         movxtod         %o4, %f0
553         movxtod         %o5, %f2
554         xor             %g4, %o2, %o4
555         xor             %g5, %o3, %o5
556         movxtod         %o4, %f4
557         movxtod         %o5, %f6
558
559         prefetch        [$inp + 32+63], 20
560         call            _${alg}${bits}_decrypt_2x
561         add             $inp, 32, $inp
562         subcc           $len, 2, $len
563
564         movxtod         %o0, %f8
565         movxtod         %o1, %f10
566         fxor            %f12, %f0, %f0          ! ^= ivec
567         fxor            %f14, %f2, %f2
568         movxtod         %o2, %f12
569         movxtod         %o3, %f14
570         fxor            %f8, %f4, %f4
571         fxor            %f10, %f6, %f6
572
573         stda            %f0, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
574         add             $out, 8, $out
575         stda            %f2, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
576         add             $out, 8, $out
577         stda            %f4, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
578         add             $out, 8, $out
579         stda            %f6, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
580         bgu,pt          $::size_t_cc, .L${bits}_cbc_dec_blk_loop2x
581         add             $out, 8, $out
582
583         add             $blk_init, $len, $len
584         andcc           $len, 1, %g0            ! is number of blocks even?
585         membar          #StoreLoad|#StoreStore
586         bnz,pt          %icc, .L${bits}_cbc_dec_loop
587         srl             $len, 0, $len
588         brnz,pn         $len, .L${bits}_cbc_dec_loop2x
589         nop
590 ___
591 $::code.=<<___ if ($::evp);
592         st              %f12, [$ivec + 0]       ! write out ivec
593         st              %f13, [$ivec + 4]
594         st              %f14, [$ivec + 8]
595         st              %f15, [$ivec + 12]
596 ___
597 $::code.=<<___ if (!$::evp);
598         brnz,pn         $ivoff, 3b
599         nop
600
601         std             %f12, [$ivec + 0]       ! write out ivec
602         std             %f14, [$ivec + 8]
603 ___
604 $::code.=<<___;
605         ret
606         restore
607 .type   ${alg}${bits}_t4_cbc_decrypt,#function
608 .size   ${alg}${bits}_t4_cbc_decrypt,.-${alg}${bits}_t4_cbc_decrypt
609 ___
610 }
611
612 sub alg_ctr32_implement {
613 my ($alg,$bits) = @_;
614
615 $::code.=<<___;
616 .globl  ${alg}${bits}_t4_ctr32_encrypt
617 .align  32
618 ${alg}${bits}_t4_ctr32_encrypt:
619         save            %sp, -$::frame, %sp
620
621         prefetch        [$inp], 20
622         prefetch        [$inp + 63], 20
623         call            _${alg}${bits}_load_enckey
624         sllx            $len, 4, $len
625
626         ld              [$ivec + 0], %l4        ! counter
627         ld              [$ivec + 4], %l5
628         ld              [$ivec + 8], %l6
629         ld              [$ivec + 12], %l7
630
631         sllx            %l4, 32, %o5
632         or              %l5, %o5, %o5
633         sllx            %l6, 32, %g1
634         xor             %o5, %g4, %g4           ! ^= rk[0]
635         xor             %g1, %g5, %g5
636         movxtod         %g4, %f14               ! most significant 64 bits
637
638         sub             $inp, $out, $blk_init   ! $inp!=$out
639         and             $inp, 7, $ileft
640         andn            $inp, 7, $inp
641         sll             $ileft, 3, $ileft
642         mov             64, $iright
643         mov             0xff, $omask
644         sub             $iright, $ileft, $iright
645         and             $out, 7, $ooff
646         cmp             $len, 255
647         movrnz          $ooff, 0, $blk_init             ! if (  $out&7 ||
648         movleu          $::size_t_cc, 0, $blk_init      !       $len<256 ||
649         brnz,pn         $blk_init, .L${bits}_ctr32_blk  !       $inp==$out)
650         srl             $omask, $ooff, $omask
651
652         andcc           $len, 16, %g0           ! is number of blocks even?
653         alignaddrl      $out, %g0, $out
654         bz              %icc, .L${bits}_ctr32_loop2x
655         srlx            $len, 4, $len
656 .L${bits}_ctr32_loop:
657         ldx             [$inp + 0], %o0
658         brz,pt          $ileft, 4f
659         ldx             [$inp + 8], %o1
660
661         ldx             [$inp + 16], %o2
662         sllx            %o0, $ileft, %o0
663         srlx            %o1, $iright, %g1
664         sllx            %o1, $ileft, %o1
665         or              %g1, %o0, %o0
666         srlx            %o2, $iright, %o2
667         or              %o2, %o1, %o1
668 4:
669         xor             %g5, %l7, %g1           ! ^= rk[0]
670         add             %l7, 1, %l7
671         movxtod         %g1, %f2
672         srl             %l7, 0, %l7             ! clruw
673         prefetch        [$out + 63], 22
674         prefetch        [$inp + 16+63], 20
675 ___
676 $::code.=<<___ if ($alg eq "aes");
677         aes_eround01    %f16, %f14, %f2, %f4
678         aes_eround23    %f18, %f14, %f2, %f2
679 ___
680 $::code.=<<___ if ($alg eq "cmll");
681         camellia_f      %f16, %f2, %f14, %f2
682         camellia_f      %f18, %f14, %f2, %f0
683 ___
684 $::code.=<<___;
685         call            _${alg}${bits}_encrypt_1x+8
686         add             $inp, 16, $inp
687
688         movxtod         %o0, %f10
689         movxtod         %o1, %f12
690         fxor            %f10, %f0, %f0          ! ^= inp
691         fxor            %f12, %f2, %f2
692
693         brnz,pn         $ooff, 2f
694         sub             $len, 1, $len
695                 
696         std             %f0, [$out + 0]
697         std             %f2, [$out + 8]
698         brnz,pt         $len, .L${bits}_ctr32_loop2x
699         add             $out, 16, $out
700
701         ret
702         restore
703
704 .align  16
705 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
706                                                 ! and ~3x deterioration
707                                                 ! in inp==out case
708         faligndata      %f0, %f0, %f4           ! handle unaligned output
709         faligndata      %f0, %f2, %f6
710         faligndata      %f2, %f2, %f8
711         stda            %f4, [$out + $omask]0xc0        ! partial store
712         std             %f6, [$out + 8]
713         add             $out, 16, $out
714         orn             %g0, $omask, $omask
715         stda            %f8, [$out + $omask]0xc0        ! partial store
716
717         brnz,pt         $len, .L${bits}_ctr32_loop2x+4
718         orn             %g0, $omask, $omask
719
720         ret
721         restore
722
723 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
724 .align  32
725 .L${bits}_ctr32_loop2x:
726         ldx             [$inp + 0], %o0
727         ldx             [$inp + 8], %o1
728         ldx             [$inp + 16], %o2
729         brz,pt          $ileft, 4f
730         ldx             [$inp + 24], %o3
731
732         ldx             [$inp + 32], %o4
733         sllx            %o0, $ileft, %o0
734         srlx            %o1, $iright, %g1
735         or              %g1, %o0, %o0
736         sllx            %o1, $ileft, %o1
737         srlx            %o2, $iright, %g1
738         or              %g1, %o1, %o1
739         sllx            %o2, $ileft, %o2
740         srlx            %o3, $iright, %g1
741         or              %g1, %o2, %o2
742         sllx            %o3, $ileft, %o3
743         srlx            %o4, $iright, %o4
744         or              %o4, %o3, %o3
745 4:
746         xor             %g5, %l7, %g1           ! ^= rk[0]
747         add             %l7, 1, %l7
748         movxtod         %g1, %f2
749         srl             %l7, 0, %l7             ! clruw
750         xor             %g5, %l7, %g1
751         add             %l7, 1, %l7
752         movxtod         %g1, %f6
753         srl             %l7, 0, %l7             ! clruw
754         prefetch        [$out + 63], 22
755         prefetch        [$inp + 32+63], 20
756 ___
757 $::code.=<<___ if ($alg eq "aes");
758         aes_eround01    %f16, %f14, %f2, %f8
759         aes_eround23    %f18, %f14, %f2, %f2
760         aes_eround01    %f16, %f14, %f6, %f10
761         aes_eround23    %f18, %f14, %f6, %f6
762 ___
763 $::code.=<<___ if ($alg eq "cmll");
764         camellia_f      %f16, %f2, %f14, %f2
765         camellia_f      %f16, %f6, %f14, %f6
766         camellia_f      %f18, %f14, %f2, %f0
767         camellia_f      %f18, %f14, %f6, %f4
768 ___
769 $::code.=<<___;
770         call            _${alg}${bits}_encrypt_2x+16
771         add             $inp, 32, $inp
772
773         movxtod         %o0, %f8
774         movxtod         %o1, %f10
775         movxtod         %o2, %f12
776         fxor            %f8, %f0, %f0           ! ^= inp
777         movxtod         %o3, %f8
778         fxor            %f10, %f2, %f2
779         fxor            %f12, %f4, %f4
780         fxor            %f8, %f6, %f6
781
782         brnz,pn         $ooff, 2f
783         sub             $len, 2, $len
784                 
785         std             %f0, [$out + 0]
786         std             %f2, [$out + 8]
787         std             %f4, [$out + 16]
788         std             %f6, [$out + 24]
789         brnz,pt         $len, .L${bits}_ctr32_loop2x
790         add             $out, 32, $out
791
792         ret
793         restore
794
795 .align  16
796 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
797                                                 ! and ~3x deterioration
798                                                 ! in inp==out case
799         faligndata      %f0, %f0, %f8           ! handle unaligned output
800         faligndata      %f0, %f2, %f0
801         faligndata      %f2, %f4, %f2
802         faligndata      %f4, %f6, %f4
803         faligndata      %f6, %f6, %f6
804
805         stda            %f8, [$out + $omask]0xc0        ! partial store
806         std             %f0, [$out + 8]
807         std             %f2, [$out + 16]
808         std             %f4, [$out + 24]
809         add             $out, 32, $out
810         orn             %g0, $omask, $omask
811         stda            %f6, [$out + $omask]0xc0        ! partial store
812
813         brnz,pt         $len, .L${bits}_ctr32_loop2x+4
814         orn             %g0, $omask, $omask
815
816         ret
817         restore
818
819 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
820 .align  32
821 .L${bits}_ctr32_blk:
822         add     $out, $len, $blk_init
823         and     $blk_init, 63, $blk_init        ! tail
824         sub     $len, $blk_init, $len
825         add     $blk_init, 15, $blk_init        ! round up to 16n
826         srlx    $len, 4, $len
827         srl     $blk_init, 4, $blk_init
828         sub     $len, 1, $len
829         add     $blk_init, 1, $blk_init
830
831 .L${bits}_ctr32_blk_loop2x:
832         ldx             [$inp + 0], %o0
833         ldx             [$inp + 8], %o1
834         ldx             [$inp + 16], %o2
835         brz,pt          $ileft, 5f
836         ldx             [$inp + 24], %o3
837
838         ldx             [$inp + 32], %o4
839         sllx            %o0, $ileft, %o0
840         srlx            %o1, $iright, %g1
841         or              %g1, %o0, %o0
842         sllx            %o1, $ileft, %o1
843         srlx            %o2, $iright, %g1
844         or              %g1, %o1, %o1
845         sllx            %o2, $ileft, %o2
846         srlx            %o3, $iright, %g1
847         or              %g1, %o2, %o2
848         sllx            %o3, $ileft, %o3
849         srlx            %o4, $iright, %o4
850         or              %o4, %o3, %o3
851 5:
852         xor             %g5, %l7, %g1           ! ^= rk[0]
853         add             %l7, 1, %l7
854         movxtod         %g1, %f2
855         srl             %l7, 0, %l7             ! clruw
856         xor             %g5, %l7, %g1
857         add             %l7, 1, %l7
858         movxtod         %g1, %f6
859         srl             %l7, 0, %l7             ! clruw
860         prefetch        [$inp + 32+63], 20
861 ___
862 $::code.=<<___ if ($alg eq "aes");
863         aes_eround01    %f16, %f14, %f2, %f8
864         aes_eround23    %f18, %f14, %f2, %f2
865         aes_eround01    %f16, %f14, %f6, %f10
866         aes_eround23    %f18, %f14, %f6, %f6
867 ___
868 $::code.=<<___ if ($alg eq "cmll");
869         camellia_f      %f16, %f2, %f14, %f2
870         camellia_f      %f16, %f6, %f14, %f6
871         camellia_f      %f18, %f14, %f2, %f0
872         camellia_f      %f18, %f14, %f6, %f4
873 ___
874 $::code.=<<___;
875         call            _${alg}${bits}_encrypt_2x+16
876         add             $inp, 32, $inp
877         subcc           $len, 2, $len
878
879         movxtod         %o0, %f8
880         movxtod         %o1, %f10
881         movxtod         %o2, %f12
882         fxor            %f8, %f0, %f0           ! ^= inp
883         movxtod         %o3, %f8
884         fxor            %f10, %f2, %f2
885         fxor            %f12, %f4, %f4
886         fxor            %f8, %f6, %f6
887
888         stda            %f0, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
889         add             $out, 8, $out
890         stda            %f2, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
891         add             $out, 8, $out
892         stda            %f4, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
893         add             $out, 8, $out
894         stda            %f6, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
895         bgu,pt          $::size_t_cc, .L${bits}_ctr32_blk_loop2x
896         add             $out, 8, $out
897
898         add             $blk_init, $len, $len
899         andcc           $len, 1, %g0            ! is number of blocks even?
900         membar          #StoreLoad|#StoreStore
901         bnz,pt          %icc, .L${bits}_ctr32_loop
902         srl             $len, 0, $len
903         brnz,pn         $len, .L${bits}_ctr32_loop2x
904         nop
905
906         ret
907         restore
908 .type   ${alg}${bits}_t4_ctr32_encrypt,#function
909 .size   ${alg}${bits}_t4_ctr32_encrypt,.-${alg}${bits}_t4_ctr32_encrypt
910 ___
911 }
912
913 sub alg_xts_implement {
914 my ($alg,$bits,$dir) = @_;
915 my ($inp,$out,$len,$key1,$key2,$ivec)=map("%i$_",(0..5));
916 my $rem=$ivec;
917
918 $::code.=<<___;
919 .globl  ${alg}${bits}_t4_xts_${dir}crypt
920 .align  32
921 ${alg}${bits}_t4_xts_${dir}crypt:
922         save            %sp, -$::frame-16, %sp
923
924         mov             $ivec, %o0
925         add             %fp, $::bias-16, %o1
926         call            ${alg}_t4_encrypt
927         mov             $key2, %o2
928
929         add             %fp, $::bias-16, %l7
930         ldxa            [%l7]0x88, %g2
931         add             %fp, $::bias-8, %l7
932         ldxa            [%l7]0x88, %g3          ! %g3:%g2 is tweak
933
934         sethi           %hi(0x76543210), %l7
935         or              %l7, %lo(0x76543210), %l7
936         bmask           %l7, %g0, %g0           ! byte swap mask
937
938         prefetch        [$inp], 20
939         prefetch        [$inp + 63], 20
940         call            _${alg}${bits}_load_${dir}ckey
941         and             $len, 15,  $rem
942         and             $len, -16, $len
943 ___
944 $code.=<<___ if ($dir eq "de");
945         mov             0, %l7
946         movrnz          $rem, 16,  %l7
947         sub             $len, %l7, $len
948 ___
949 $code.=<<___;
950
951         sub             $inp, $out, $blk_init   ! $inp!=$out
952         and             $inp, 7, $ileft
953         andn            $inp, 7, $inp
954         sll             $ileft, 3, $ileft
955         mov             64, $iright
956         mov             0xff, $omask
957         sub             $iright, $ileft, $iright
958         and             $out, 7, $ooff
959         cmp             $len, 255
960         movrnz          $ooff, 0, $blk_init             ! if (  $out&7 ||
961         movleu          $::size_t_cc, 0, $blk_init      !       $len<256 ||
962         brnz,pn         $blk_init, .L${bits}_xts_${dir}blk !    $inp==$out)
963         srl             $omask, $ooff, $omask
964
965         andcc           $len, 16, %g0           ! is number of blocks even?
966 ___
967 $code.=<<___ if ($dir eq "de");
968         brz,pn          $len, .L${bits}_xts_${dir}steal
969 ___
970 $code.=<<___;
971         alignaddrl      $out, %g0, $out
972         bz              %icc, .L${bits}_xts_${dir}loop2x
973         srlx            $len, 4, $len
974 .L${bits}_xts_${dir}loop:
975         ldx             [$inp + 0], %o0
976         brz,pt          $ileft, 4f
977         ldx             [$inp + 8], %o1
978
979         ldx             [$inp + 16], %o2
980         sllx            %o0, $ileft, %o0
981         srlx            %o1, $iright, %g1
982         sllx            %o1, $ileft, %o1
983         or              %g1, %o0, %o0
984         srlx            %o2, $iright, %o2
985         or              %o2, %o1, %o1
986 4:
987         movxtod         %g2, %f12
988         movxtod         %g3, %f14
989         bshuffle        %f12, %f12, %f12
990         bshuffle        %f14, %f14, %f14
991
992         xor             %g4, %o0, %o0           ! ^= rk[0]
993         xor             %g5, %o1, %o1
994         movxtod         %o0, %f0
995         movxtod         %o1, %f2
996
997         fxor            %f12, %f0, %f0          ! ^= tweak[0]
998         fxor            %f14, %f2, %f2
999
1000         prefetch        [$out + 63], 22
1001         prefetch        [$inp + 16+63], 20
1002         call            _${alg}${bits}_${dir}crypt_1x
1003         add             $inp, 16, $inp
1004
1005         fxor            %f12, %f0, %f0          ! ^= tweak[0]
1006         fxor            %f14, %f2, %f2
1007
1008         srax            %g3, 63, %l7            ! next tweak value
1009         addcc           %g2, %g2, %g2
1010         and             %l7, 0x87, %l7
1011         addxc           %g3, %g3, %g3
1012         xor             %l7, %g2, %g2
1013
1014         brnz,pn         $ooff, 2f
1015         sub             $len, 1, $len
1016                 
1017         std             %f0, [$out + 0]
1018         std             %f2, [$out + 8]
1019         brnz,pt         $len, .L${bits}_xts_${dir}loop2x
1020         add             $out, 16, $out
1021
1022         brnz,pn         $rem, .L${bits}_xts_${dir}steal
1023         nop
1024
1025         ret
1026         restore
1027
1028 .align  16
1029 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
1030                                                 ! and ~3x deterioration
1031                                                 ! in inp==out case
1032         faligndata      %f0, %f0, %f4           ! handle unaligned output
1033         faligndata      %f0, %f2, %f6
1034         faligndata      %f2, %f2, %f8
1035         stda            %f4, [$out + $omask]0xc0        ! partial store
1036         std             %f6, [$out + 8]
1037         add             $out, 16, $out
1038         orn             %g0, $omask, $omask
1039         stda            %f8, [$out + $omask]0xc0        ! partial store
1040
1041         brnz,pt         $len, .L${bits}_xts_${dir}loop2x+4
1042         orn             %g0, $omask, $omask
1043
1044         brnz,pn         $rem, .L${bits}_xts_${dir}steal
1045         nop
1046
1047         ret
1048         restore
1049
1050 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1051 .align  32
1052 .L${bits}_xts_${dir}loop2x:
1053         ldx             [$inp + 0], %o0
1054         ldx             [$inp + 8], %o1
1055         ldx             [$inp + 16], %o2
1056         brz,pt          $ileft, 4f
1057         ldx             [$inp + 24], %o3
1058
1059         ldx             [$inp + 32], %o4
1060         sllx            %o0, $ileft, %o0
1061         srlx            %o1, $iright, %g1
1062         or              %g1, %o0, %o0
1063         sllx            %o1, $ileft, %o1
1064         srlx            %o2, $iright, %g1
1065         or              %g1, %o1, %o1
1066         sllx            %o2, $ileft, %o2
1067         srlx            %o3, $iright, %g1
1068         or              %g1, %o2, %o2
1069         sllx            %o3, $ileft, %o3
1070         srlx            %o4, $iright, %o4
1071         or              %o4, %o3, %o3
1072 4:
1073         movxtod         %g2, %f12
1074         movxtod         %g3, %f14
1075         bshuffle        %f12, %f12, %f12
1076         bshuffle        %f14, %f14, %f14
1077
1078         srax            %g3, 63, %l7            ! next tweak value
1079         addcc           %g2, %g2, %g2
1080         and             %l7, 0x87, %l7
1081         addxc           %g3, %g3, %g3
1082         xor             %l7, %g2, %g2
1083
1084         movxtod         %g2, %f8
1085         movxtod         %g3, %f10
1086         bshuffle        %f8,  %f8,  %f8
1087         bshuffle        %f10, %f10, %f10
1088
1089         xor             %g4, %o0, %o0           ! ^= rk[0]
1090         xor             %g5, %o1, %o1
1091         xor             %g4, %o2, %o2           ! ^= rk[0]
1092         xor             %g5, %o3, %o3
1093         movxtod         %o0, %f0
1094         movxtod         %o1, %f2
1095         movxtod         %o2, %f4
1096         movxtod         %o3, %f6
1097
1098         fxor            %f12, %f0, %f0          ! ^= tweak[0]
1099         fxor            %f14, %f2, %f2
1100         fxor            %f8,  %f4, %f4          ! ^= tweak[0]
1101         fxor            %f10, %f6, %f6
1102
1103         prefetch        [$out + 63], 22
1104         prefetch        [$inp + 32+63], 20
1105         call            _${alg}${bits}_${dir}crypt_2x
1106         add             $inp, 32, $inp
1107
1108         movxtod         %g2, %f8
1109         movxtod         %g3, %f10
1110
1111         srax            %g3, 63, %l7            ! next tweak value
1112         addcc           %g2, %g2, %g2
1113         and             %l7, 0x87, %l7
1114         addxc           %g3, %g3, %g3
1115         xor             %l7, %g2, %g2
1116
1117         bshuffle        %f8,  %f8,  %f8
1118         bshuffle        %f10, %f10, %f10
1119
1120         fxor            %f12, %f0, %f0          ! ^= tweak[0]
1121         fxor            %f14, %f2, %f2
1122         fxor            %f8,  %f4, %f4
1123         fxor            %f10, %f6, %f6
1124
1125         brnz,pn         $ooff, 2f
1126         sub             $len, 2, $len
1127                 
1128         std             %f0, [$out + 0]
1129         std             %f2, [$out + 8]
1130         std             %f4, [$out + 16]
1131         std             %f6, [$out + 24]
1132         brnz,pt         $len, .L${bits}_xts_${dir}loop2x
1133         add             $out, 32, $out
1134
1135         fsrc2           %f4, %f0
1136         fsrc2           %f6, %f2
1137         brnz,pn         $rem, .L${bits}_xts_${dir}steal
1138         nop
1139
1140         ret
1141         restore
1142
1143 .align  16
1144 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
1145                                                 ! and ~3x deterioration
1146                                                 ! in inp==out case
1147         faligndata      %f0, %f0, %f8           ! handle unaligned output
1148         faligndata      %f0, %f2, %f10
1149         faligndata      %f2, %f4, %f12
1150         faligndata      %f4, %f6, %f14
1151         faligndata      %f6, %f6, %f0
1152
1153         stda            %f8, [$out + $omask]0xc0        ! partial store
1154         std             %f10, [$out + 8]
1155         std             %f12, [$out + 16]
1156         std             %f14, [$out + 24]
1157         add             $out, 32, $out
1158         orn             %g0, $omask, $omask
1159         stda            %f0, [$out + $omask]0xc0        ! partial store
1160
1161         brnz,pt         $len, .L${bits}_xts_${dir}loop2x+4
1162         orn             %g0, $omask, $omask
1163
1164         fsrc2           %f4, %f0
1165         fsrc2           %f6, %f2
1166         brnz,pn         $rem, .L${bits}_xts_${dir}steal
1167         nop
1168
1169         ret
1170         restore
1171
1172 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1173 .align  32
1174 .L${bits}_xts_${dir}blk:
1175         add     $out, $len, $blk_init
1176         and     $blk_init, 63, $blk_init        ! tail
1177         sub     $len, $blk_init, $len
1178         add     $blk_init, 15, $blk_init        ! round up to 16n
1179         srlx    $len, 4, $len
1180         srl     $blk_init, 4, $blk_init
1181         sub     $len, 1, $len
1182         add     $blk_init, 1, $blk_init
1183
1184 .L${bits}_xts_${dir}blk2x:
1185         ldx             [$inp + 0], %o0
1186         ldx             [$inp + 8], %o1
1187         ldx             [$inp + 16], %o2
1188         brz,pt          $ileft, 5f
1189         ldx             [$inp + 24], %o3
1190
1191         ldx             [$inp + 32], %o4
1192         sllx            %o0, $ileft, %o0
1193         srlx            %o1, $iright, %g1
1194         or              %g1, %o0, %o0
1195         sllx            %o1, $ileft, %o1
1196         srlx            %o2, $iright, %g1
1197         or              %g1, %o1, %o1
1198         sllx            %o2, $ileft, %o2
1199         srlx            %o3, $iright, %g1
1200         or              %g1, %o2, %o2
1201         sllx            %o3, $ileft, %o3
1202         srlx            %o4, $iright, %o4
1203         or              %o4, %o3, %o3
1204 5:
1205         movxtod         %g2, %f12
1206         movxtod         %g3, %f14
1207         bshuffle        %f12, %f12, %f12
1208         bshuffle        %f14, %f14, %f14
1209
1210         srax            %g3, 63, %l7            ! next tweak value
1211         addcc           %g2, %g2, %g2
1212         and             %l7, 0x87, %l7
1213         addxc           %g3, %g3, %g3
1214         xor             %l7, %g2, %g2
1215
1216         movxtod         %g2, %f8
1217         movxtod         %g3, %f10
1218         bshuffle        %f8,  %f8,  %f8
1219         bshuffle        %f10, %f10, %f10
1220
1221         xor             %g4, %o0, %o0           ! ^= rk[0]
1222         xor             %g5, %o1, %o1
1223         xor             %g4, %o2, %o2           ! ^= rk[0]
1224         xor             %g5, %o3, %o3
1225         movxtod         %o0, %f0
1226         movxtod         %o1, %f2
1227         movxtod         %o2, %f4
1228         movxtod         %o3, %f6
1229
1230         fxor            %f12, %f0, %f0          ! ^= tweak[0]
1231         fxor            %f14, %f2, %f2
1232         fxor            %f8,  %f4, %f4          ! ^= tweak[0]
1233         fxor            %f10, %f6, %f6
1234
1235         prefetch        [$inp + 32+63], 20
1236         call            _${alg}${bits}_${dir}crypt_2x
1237         add             $inp, 32, $inp
1238
1239         movxtod         %g2, %f8
1240         movxtod         %g3, %f10
1241
1242         srax            %g3, 63, %l7            ! next tweak value
1243         addcc           %g2, %g2, %g2
1244         and             %l7, 0x87, %l7
1245         addxc           %g3, %g3, %g3
1246         xor             %l7, %g2, %g2
1247
1248         bshuffle        %f8,  %f8,  %f8
1249         bshuffle        %f10, %f10, %f10
1250
1251         fxor            %f12, %f0, %f0          ! ^= tweak[0]
1252         fxor            %f14, %f2, %f2
1253         fxor            %f8,  %f4, %f4
1254         fxor            %f10, %f6, %f6
1255
1256         subcc           $len, 2, $len
1257         stda            %f0, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
1258         add             $out, 8, $out
1259         stda            %f2, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
1260         add             $out, 8, $out
1261         stda            %f4, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
1262         add             $out, 8, $out
1263         stda            %f6, [$out]0xe2         ! ASI_BLK_INIT, T4-specific
1264         bgu,pt          $::size_t_cc, .L${bits}_xts_${dir}blk2x
1265         add             $out, 8, $out
1266
1267         add             $blk_init, $len, $len
1268         andcc           $len, 1, %g0            ! is number of blocks even?
1269         membar          #StoreLoad|#StoreStore
1270         bnz,pt          %icc, .L${bits}_xts_${dir}loop
1271         srl             $len, 0, $len
1272         brnz,pn         $len, .L${bits}_xts_${dir}loop2x
1273         nop
1274
1275         fsrc2           %f4, %f0
1276         fsrc2           %f6, %f2
1277         brnz,pn         $rem, .L${bits}_xts_${dir}steal
1278         nop
1279
1280         ret
1281         restore
1282 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1283 ___
1284 $code.=<<___ if ($dir eq "en");
1285 .align  32
1286 .L${bits}_xts_${dir}steal:
1287         std             %f0, [%fp + $::bias-16] ! copy of output
1288         std             %f2, [%fp + $::bias-8]
1289
1290         srl             $ileft, 3, $ileft
1291         add             %fp, $::bias-16, %l7
1292         add             $inp, $ileft, $inp      ! original $inp+$len&-15
1293         add             $out, $ooff, $out       ! original $out+$len&-15
1294         mov             0, $ileft
1295         nop                                     ! align
1296
1297 .L${bits}_xts_${dir}stealing:
1298         ldub            [$inp + $ileft], %o0
1299         ldub            [%l7  + $ileft], %o1
1300         dec             $rem
1301         stb             %o0, [%l7  + $ileft]
1302         stb             %o1, [$out + $ileft]
1303         brnz            $rem, .L${bits}_xts_${dir}stealing
1304         inc             $ileft
1305
1306         mov             %l7, $inp
1307         sub             $out, 16, $out
1308         mov             0, $ileft
1309         sub             $out, $ooff, $out
1310         ba              .L${bits}_xts_${dir}loop        ! one more time
1311         mov             1, $len                         ! $rem is 0
1312 ___
1313 $code.=<<___ if ($dir eq "de");
1314 .align  32
1315 .L${bits}_xts_${dir}steal:
1316         ldx             [$inp + 0], %o0
1317         brz,pt          $ileft, 8f
1318         ldx             [$inp + 8], %o1
1319
1320         ldx             [$inp + 16], %o2
1321         sllx            %o0, $ileft, %o0
1322         srlx            %o1, $iright, %g1
1323         sllx            %o1, $ileft, %o1
1324         or              %g1, %o0, %o0
1325         srlx            %o2, $iright, %o2
1326         or              %o2, %o1, %o1
1327 8:
1328         srax            %g3, 63, %l7            ! next tweak value
1329         addcc           %g2, %g2, %o2
1330         and             %l7, 0x87, %l7
1331         addxc           %g3, %g3, %o3
1332         xor             %l7, %o2, %o2
1333
1334         movxtod         %o2, %f12
1335         movxtod         %o3, %f14
1336         bshuffle        %f12, %f12, %f12
1337         bshuffle        %f14, %f14, %f14
1338
1339         xor             %g4, %o0, %o0           ! ^= rk[0]
1340         xor             %g5, %o1, %o1
1341         movxtod         %o0, %f0
1342         movxtod         %o1, %f2
1343
1344         fxor            %f12, %f0, %f0          ! ^= tweak[0]
1345         fxor            %f14, %f2, %f2
1346
1347         call            _${alg}${bits}_${dir}crypt_1x
1348         add             $inp, 16, $inp
1349
1350         fxor            %f12, %f0, %f0          ! ^= tweak[0]
1351         fxor            %f14, %f2, %f2
1352
1353         std             %f0, [%fp + $::bias-16]
1354         std             %f2, [%fp + $::bias-8]
1355
1356         srl             $ileft, 3, $ileft
1357         add             %fp, $::bias-16, %l7
1358         add             $inp, $ileft, $inp      ! original $inp+$len&-15
1359         add             $out, $ooff, $out       ! original $out+$len&-15
1360         mov             0, $ileft
1361         add             $out, 16, $out
1362         nop                                     ! align
1363
1364 .L${bits}_xts_${dir}stealing:
1365         ldub            [$inp + $ileft], %o0
1366         ldub            [%l7  + $ileft], %o1
1367         dec             $rem
1368         stb             %o0, [%l7  + $ileft]
1369         stb             %o1, [$out + $ileft]
1370         brnz            $rem, .L${bits}_xts_${dir}stealing
1371         inc             $ileft
1372
1373         mov             %l7, $inp
1374         sub             $out, 16, $out
1375         mov             0, $ileft
1376         sub             $out, $ooff, $out
1377         ba              .L${bits}_xts_${dir}loop        ! one more time
1378         mov             1, $len                         ! $rem is 0
1379 ___
1380 $code.=<<___;
1381         ret
1382         restore
1383 .type   ${alg}${bits}_t4_xts_${dir}crypt,#function
1384 .size   ${alg}${bits}_t4_xts_${dir}crypt,.-${alg}${bits}_t4_xts_${dir}crypt
1385 ___
1386 }
1387
1388 # Purpose of these subroutines is to explicitly encode VIS instructions,
1389 # so that one can compile the module without having to specify VIS
1390 # extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a.
1391 # Idea is to reserve for option to produce "universal" binary and let
1392 # programmer detect if current CPU is VIS capable at run-time.
1393 sub unvis {
1394 my ($mnemonic,$rs1,$rs2,$rd)=@_;
1395 my ($ref,$opf);
1396 my %visopf = (  "faligndata"    => 0x048,
1397                 "bshuffle"      => 0x04c,
1398                 "fnot2"         => 0x066,
1399                 "fxor"          => 0x06c,
1400                 "fsrc2"         => 0x078        );
1401
1402     $ref = "$mnemonic\t$rs1,$rs2,$rd";
1403
1404     if ($opf=$visopf{$mnemonic}) {
1405         foreach ($rs1,$rs2,$rd) {
1406             return $ref if (!/%f([0-9]{1,2})/);
1407             $_=$1;
1408             if ($1>=32) {
1409                 return $ref if ($1&1);
1410                 # re-encode for upper double register addressing
1411                 $_=($1|$1>>5)&31;
1412             }
1413         }
1414
1415         return  sprintf ".word\t0x%08x !%s",
1416                         0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
1417                         $ref;
1418     } else {
1419         return $ref;
1420     }
1421 }
1422
1423 sub unvis3 {
1424 my ($mnemonic,$rs1,$rs2,$rd)=@_;
1425 my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 );
1426 my ($ref,$opf);
1427 my %visopf = (  "addxc"         => 0x011,
1428                 "addxccc"       => 0x013,
1429                 "umulxhi"       => 0x016,
1430                 "alignaddr"     => 0x018,
1431                 "bmask"         => 0x019,
1432                 "alignaddrl"    => 0x01a        );
1433
1434     $ref = "$mnemonic\t$rs1,$rs2,$rd";
1435
1436     if ($opf=$visopf{$mnemonic}) {
1437         foreach ($rs1,$rs2,$rd) {
1438             return $ref if (!/%([goli])([0-9])/);
1439             $_=$bias{$1}+$2;
1440         }
1441
1442         return  sprintf ".word\t0x%08x !%s",
1443                         0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
1444                         $ref;
1445     } else {
1446         return $ref;
1447     }
1448 }
1449
1450 sub unaes_round {       # 4-argument instructions
1451 my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
1452 my ($ref,$opf);
1453 my %aesopf = (  "aes_eround01"  => 0,
1454                 "aes_eround23"  => 1,
1455                 "aes_dround01"  => 2,
1456                 "aes_dround23"  => 3,
1457                 "aes_eround01_l"=> 4,
1458                 "aes_eround23_l"=> 5,
1459                 "aes_dround01_l"=> 6,
1460                 "aes_dround23_l"=> 7,
1461                 "aes_kexpand1"  => 8    );
1462
1463     $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
1464
1465     if (defined($opf=$aesopf{$mnemonic})) {
1466         $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3;
1467         foreach ($rs1,$rs2,$rd) {
1468             return $ref if (!/%f([0-9]{1,2})/);
1469             $_=$1;
1470             if ($1>=32) {
1471                 return $ref if ($1&1);
1472                 # re-encode for upper double register addressing
1473                 $_=($1|$1>>5)&31;
1474             }
1475         }
1476
1477         return  sprintf ".word\t0x%08x !%s",
1478                         2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|$opf<<5|$rs2,
1479                         $ref;
1480     } else {
1481         return $ref;
1482     }
1483 }
1484
1485 sub unaes_kexpand {     # 3-argument instructions
1486 my ($mnemonic,$rs1,$rs2,$rd)=@_;
1487 my ($ref,$opf);
1488 my %aesopf = (  "aes_kexpand0"  => 0x130,
1489                 "aes_kexpand2"  => 0x131        );
1490
1491     $ref = "$mnemonic\t$rs1,$rs2,$rd";
1492
1493     if (defined($opf=$aesopf{$mnemonic})) {
1494         foreach ($rs1,$rs2,$rd) {
1495             return $ref if (!/%f([0-9]{1,2})/);
1496             $_=$1;
1497             if ($1>=32) {
1498                 return $ref if ($1&1);
1499                 # re-encode for upper double register addressing
1500                 $_=($1|$1>>5)&31;
1501             }
1502         }
1503
1504         return  sprintf ".word\t0x%08x !%s",
1505                         2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
1506                         $ref;
1507     } else {
1508         return $ref;
1509     }
1510 }
1511
1512 sub uncamellia_f {      # 4-argument instructions
1513 my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
1514 my ($ref,$opf);
1515
1516     $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
1517
1518     if (1) {
1519         $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3;
1520         foreach ($rs1,$rs2,$rd) {
1521             return $ref if (!/%f([0-9]{1,2})/);
1522             $_=$1;
1523             if ($1>=32) {
1524                 return $ref if ($1&1);
1525                 # re-encode for upper double register addressing
1526                 $_=($1|$1>>5)&31;
1527             }
1528         }
1529
1530         return  sprintf ".word\t0x%08x !%s",
1531                         2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|0xc<<5|$rs2,
1532                         $ref;
1533     } else {
1534         return $ref;
1535     }
1536 }
1537
1538 sub uncamellia3 {       # 3-argument instructions
1539 my ($mnemonic,$rs1,$rs2,$rd)=@_;
1540 my ($ref,$opf);
1541 my %cmllopf = ( "camellia_fl"   => 0x13c,
1542                 "camellia_fli"  => 0x13d        );
1543
1544     $ref = "$mnemonic\t$rs1,$rs2,$rd";
1545
1546     if (defined($opf=$cmllopf{$mnemonic})) {
1547         foreach ($rs1,$rs2,$rd) {
1548             return $ref if (!/%f([0-9]{1,2})/);
1549             $_=$1;
1550             if ($1>=32) {
1551                 return $ref if ($1&1);
1552                 # re-encode for upper double register addressing
1553                 $_=($1|$1>>5)&31;
1554             }
1555         }
1556
1557         return  sprintf ".word\t0x%08x !%s",
1558                         2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
1559                         $ref;
1560     } else {
1561         return $ref;
1562     }
1563 }
1564
1565 sub unmovxtox {         # 2-argument instructions
1566 my ($mnemonic,$rs,$rd)=@_;
1567 my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24, "f" => 0 );
1568 my ($ref,$opf);
1569 my %movxopf = ( "movdtox"       => 0x110,
1570                 "movstouw"      => 0x111,
1571                 "movstosw"      => 0x113,
1572                 "movxtod"       => 0x118,
1573                 "movwtos"       => 0x119        );
1574
1575     $ref = "$mnemonic\t$rs,$rd";
1576
1577     if (defined($opf=$movxopf{$mnemonic})) {
1578         foreach ($rs,$rd) {
1579             return $ref if (!/%([fgoli])([0-9]{1,2})/);
1580             $_=$bias{$1}+$2;
1581             if ($2>=32) {
1582                 return $ref if ($2&1);
1583                 # re-encode for upper double register addressing
1584                 $_=($2|$2>>5)&31;
1585             }
1586         }
1587
1588         return  sprintf ".word\t0x%08x !%s",
1589                         2<<30|$rd<<25|0x36<<19|$opf<<5|$rs,
1590                         $ref;
1591     } else {
1592         return $ref;
1593     }
1594 }
1595
1596 sub undes {
1597 my ($mnemonic)=shift;
1598 my @args=@_;
1599 my ($ref,$opf);
1600 my %desopf = (  "des_round"     => 0b1001,
1601                 "des_ip"        => 0b100110100,
1602                 "des_iip"       => 0b100110101,
1603                 "des_kexpand"   => 0b100110110  );
1604
1605     $ref = "$mnemonic\t".join(",",@_);
1606
1607     if (defined($opf=$desopf{$mnemonic})) {     # 4-arg
1608         if ($mnemonic eq "des_round") {
1609             foreach (@args[0..3]) {
1610                 return $ref if (!/%f([0-9]{1,2})/);
1611                 $_=$1;
1612                 if ($1>=32) {
1613                     return $ref if ($1&1);
1614                     # re-encode for upper double register addressing
1615                     $_=($1|$1>>5)&31;
1616                 }
1617             }
1618             return  sprintf ".word\t0x%08x !%s",
1619                             2<<30|0b011001<<19|$opf<<5|$args[0]<<14|$args[1]|$args[2]<<9|$args[3]<<25,
1620                             $ref;
1621         } elsif ($mnemonic eq "des_kexpand") {  # 3-arg
1622             foreach (@args[0..2]) {
1623                 return $ref if (!/(%f)?([0-9]{1,2})/);
1624                 $_=$2;
1625                 if ($2>=32) {
1626                     return $ref if ($2&1);
1627                     # re-encode for upper double register addressing
1628                     $_=($2|$2>>5)&31;
1629                 }
1630             }
1631             return  sprintf ".word\t0x%08x !%s",
1632                             2<<30|0b110110<<19|$opf<<5|$args[0]<<14|$args[1]|$args[2]<<25,
1633                             $ref;
1634         } else {                                # 2-arg
1635             foreach (@args[0..1]) {
1636                 return $ref if (!/%f([0-9]{1,2})/);
1637                 $_=$1;
1638                 if ($1>=32) {
1639                     return $ref if ($2&1);
1640                     # re-encode for upper double register addressing
1641                     $_=($1|$1>>5)&31;
1642                 }
1643             }
1644             return  sprintf ".word\t0x%08x !%s",
1645                             2<<30|0b110110<<19|$opf<<5|$args[0]<<14|$args[1]<<25,
1646                             $ref;
1647         }
1648     } else {
1649         return $ref;
1650     }
1651 }
1652
1653 sub emit_assembler {
1654     foreach (split("\n",$::code)) {
1655         s/\`([^\`]*)\`/eval $1/ge;
1656
1657         s/\b(f[a-z]+2[sd]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})\s*$/$1\t%f0,$2,$3/go;
1658
1659         s/\b(aes_[edk][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
1660                 &unaes_round($1,$2,$3,$4,$5)
1661          /geo or
1662         s/\b(aes_kexpand[02])\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
1663                 &unaes_kexpand($1,$2,$3,$4)
1664          /geo or
1665         s/\b(camellia_f)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
1666                 &uncamellia_f($1,$2,$3,$4,$5)
1667          /geo or
1668         s/\b(camellia_[^s]+)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
1669                 &uncamellia3($1,$2,$3,$4)
1670          /geo or
1671         s/\b(des_\w+)\s+(%f[0-9]{1,2}),\s*([%fx0-9]+)(?:,\s*(%f[0-9]{1,2})(?:,\s*(%f[0-9]{1,2}))?)?/
1672                 &undes($1,$2,$3,$4,$5)
1673          /geo or
1674         s/\b(mov[ds]to\w+)\s+(%f[0-9]{1,2}),\s*(%[goli][0-7])/
1675                 &unmovxtox($1,$2,$3)
1676          /geo or
1677         s/\b(mov[xw]to[ds])\s+(%[goli][0-7]),\s*(%f[0-9]{1,2})/
1678                 &unmovxtox($1,$2,$3)
1679          /geo or
1680         s/\b([fb][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
1681                 &unvis($1,$2,$3,$4)
1682          /geo or
1683         s/\b(umulxhi|bmask|addxc[c]{0,2}|alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/
1684                 &unvis3($1,$2,$3,$4)
1685          /geo;
1686
1687         print $_,"\n";
1688     }
1689 }
1690
1691 1;