SPARC assembly pack: add missing .type directives.
[openssl.git] / crypto / aes / asm / aesfx-sparcv9.pl
1 #! /usr/bin/env perl
2 # Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the OpenSSL license (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 #
10 # ====================================================================
11 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 # project. The module is, however, dual licensed under OpenSSL and
13 # CRYPTOGAMS licenses depending on where you obtain it. For further
14 # details see http://www.openssl.org/~appro/cryptogams/.
15 # ====================================================================
16
17 # March 2016
18 #
19 # Initial support for Fujitsu SPARC64 X/X+ comprises minimally
20 # required key setup and single-block procedures.
21
22 $output = pop;
23 open STDOUT,">$output";
24
25 {
26 my ($inp,$out,$key,$rounds,$tmp,$mask) = map("%o$_",(0..5));
27
28 $code.=<<___;
29 .text
30
31 .globl  aes_fx_encrypt
32 .align  32
33 aes_fx_encrypt:
34         and             $inp, 7, $tmp           ! is input aligned?
35         alignaddr       $inp, %g0, $inp
36         ld              [$key + 240], $rounds
37         ldd             [$key +  0], %f6
38         ldd             [$key +  8], %f8
39
40         ldd             [$inp + 0], %f0         ! load input
41         brz,pt          $tmp, .Lenc_inp_aligned
42         ldd             [$inp + 8], %f2
43
44         ldd             [$inp + 16], %f4
45         faligndata      %f0, %f2, %f0
46         faligndata      %f2, %f4, %f2
47
48 .Lenc_inp_aligned:
49         ldd             [$key + 16], %f10
50         ldd             [$key + 24], %f12
51         add             $key, 32, $key
52
53         fxor            %f0, %f6, %f0           ! ^=round[0]
54         fxor            %f2, %f8, %f2
55         ldd             [$key +  0], %f6
56         ldd             [$key +  8], %f8
57         sub             $rounds, 4, $rounds
58
59 .Loop_enc:
60         fmovd           %f0, %f4
61         faesencx        %f2, %f10, %f0
62         faesencx        %f4, %f12, %f2
63         ldd             [$key + 16], %f10
64         ldd             [$key + 24], %f12
65         add             $key, 32, $key
66
67         fmovd           %f0, %f4
68         faesencx        %f2, %f6, %f0
69         faesencx        %f4, %f8, %f2
70         ldd             [$key +  0], %f6
71         ldd             [$key +  8], %f8
72
73         brnz,a          $rounds, .Loop_enc
74         sub             $rounds, 2, $rounds
75
76         andcc           $out, 7, $tmp           ! is output aligned?
77         mov             0xff, $mask
78         alignaddrl      $out, %g0, $out
79         srl             $mask, $tmp, $mask
80
81         fmovd           %f0, %f4
82         faesencx        %f2, %f10, %f0
83         faesencx        %f4, %f12, %f2
84         fmovd           %f0, %f4
85         faesenclx       %f2, %f6, %f0
86         faesenclx       %f4, %f8, %f2
87
88         bnz,pn          %icc, .Lenc_out_unaligned
89         nop
90
91         std             %f0, [$out + 0]
92         retl
93         std             %f2, [$out + 8]
94
95 .Lenc_out_unaligned:
96         faligndata      %f0, %f0, %f4
97         faligndata      %f0, %f2, %f6
98         faligndata      %f2, %f2, %f8
99
100         stda            %f4, [$out + $mask]0xc0 ! partial store
101         std             %f6, [$out + 8]
102         add             $out, 16, $out
103         orn             %g0, $mask, $mask
104         retl
105         stda            %f8, [$out + $mask]0xc0 ! partial store
106 .type   aes_fx_encrypt,#function
107 .size   aes_fx_encrypt,.-aes_fx_encrypt
108
109 .globl  aes_fx_decrypt
110 .align  32
111 aes_fx_decrypt:
112         and             $inp, 7, $tmp           ! is input aligned?
113         alignaddr       $inp, %g0, $inp
114         ld              [$key + 240], $rounds
115         ldd             [$key +  0], %f6
116         ldd             [$key +  8], %f8
117
118         ldd             [$inp + 0], %f0         ! load input
119         brz,pt          $tmp, .Ldec_inp_aligned
120         ldd             [$inp + 8], %f2
121
122         ldd             [$inp + 16], %f4
123         faligndata      %f0, %f2, %f0
124         faligndata      %f2, %f4, %f2
125
126 .Ldec_inp_aligned:
127         ldd             [$key + 16], %f10
128         ldd             [$key + 24], %f12
129         add             $key, 32, $key
130
131         fxor            %f0, %f6, %f0           ! ^=round[0]
132         fxor            %f2, %f8, %f2
133         ldd             [$key +  0], %f6
134         ldd             [$key +  8], %f8
135         sub             $rounds, 4, $rounds
136
137 .Loop_dec:
138         fmovd           %f0, %f4
139         faesdecx        %f2, %f10, %f0
140         faesdecx        %f4, %f12, %f2
141         ldd             [$key + 16], %f10
142         ldd             [$key + 24], %f12
143         add             $key, 32, $key
144
145         fmovd           %f0, %f4
146         faesdecx        %f2, %f6, %f0
147         faesdecx        %f4, %f8, %f2
148         ldd             [$key +  0], %f6
149         ldd             [$key +  8], %f8
150
151         brnz,a          $rounds, .Loop_dec
152         sub             $rounds, 2, $rounds
153
154         andcc           $out, 7, $tmp           ! is output aligned?
155         mov             0xff, $mask
156         alignaddrl      $out, %g0, $out
157         srl             $mask, $tmp, $mask
158
159         fmovd           %f0, %f4
160         faesdecx        %f2, %f10, %f0
161         faesdecx        %f4, %f12, %f2
162         fmovd           %f0, %f4
163         faesdeclx       %f2, %f6, %f0
164         faesdeclx       %f4, %f8, %f2
165
166         bnz,pn          %icc, .Ldec_out_unaligned
167         nop
168
169         std             %f0, [$out + 0]
170         retl
171         std             %f2, [$out + 8]
172
173 .Ldec_out_unaligned:
174         faligndata      %f0, %f0, %f4
175         faligndata      %f0, %f2, %f6
176         faligndata      %f2, %f2, %f8
177
178         stda            %f4, [$out + $mask]0xc0 ! partial store
179         std             %f6, [$out + 8]
180         add             $out, 16, $out
181         orn             %g0, $mask, $mask
182         retl
183         stda            %f8, [$out + $mask]0xc0 ! partial store
184 .type   aes_fx_decrypt,#function
185 .size   aes_fx_decrypt,.-aes_fx_decrypt
186 ___
187 }
188 {
189 my ($inp,$bits,$out,$tmp,$inc) = map("%o$_",(0..5));
190 $code.=<<___;
191 .globl  aes_fx_set_decrypt_key
192 .align  32
193 aes_fx_set_decrypt_key:
194         b               .Lset_encrypt_key
195         mov             -1, $inc
196         retl
197         nop
198 .type   aes_fx_set_decrypt_key,#function
199 .size   aes_fx_set_decrypt_key,.-aes_fx_set_decrypt_key
200
201 .globl  aes_fx_set_encrypt_key
202 .align  32
203 aes_fx_set_encrypt_key:
204         mov             1, $inc
205 .Lset_encrypt_key:
206         and             $inp, 7, $tmp
207         alignaddr       $inp, %g0, $inp
208         nop
209
210         cmp             $bits, 192
211         ldd             [$inp + 0], %f0
212         bl,pt           %icc, .L128
213         ldd             [$inp + 8], %f2
214
215         be,pt           %icc, .L192
216         ldd             [$inp + 16], %f4
217         brz,pt          $tmp, .L256aligned
218         ldd             [$inp + 24], %f6
219
220         ldd             [$inp + 32], %f8
221         faligndata      %f0, %f2, %f0
222         faligndata      %f2, %f4, %f2
223         faligndata      %f4, %f6, %f4
224         faligndata      %f6, %f8, %f6
225
226 .L256aligned:
227         mov             14, $bits
228         and             $inc, `14*16`, $tmp
229         st              $bits, [$out + 240]     ! store rounds
230         add             $out, $tmp, $out        ! start or end of key schedule
231         sllx            $inc, 4, $inc           ! 16 or -16
232 ___
233 for ($i=0; $i<6; $i++) {
234     $code.=<<___;
235         std             %f0, [$out + 0]
236         faeskeyx        %f6, `0x10+$i`, %f0
237         std             %f2, [$out + 8]
238         add             $out, $inc, $out
239         faeskeyx        %f0, 0x00, %f2
240         std             %f4, [$out + 0]
241         faeskeyx        %f2, 0x01, %f4
242         std             %f6, [$out + 8]
243         add             $out, $inc, $out
244         faeskeyx        %f4, 0x00, %f6
245 ___
246 }
247 $code.=<<___;
248         std             %f0, [$out + 0]
249         faeskeyx        %f6, `0x10+$i`, %f0
250         std             %f2, [$out + 8]
251         add             $out, $inc, $out
252         faeskeyx        %f0, 0x00, %f2
253         std             %f4,[$out+0]
254         std             %f6,[$out+8]
255         add             $out, $inc, $out
256         std             %f0,[$out+0]
257         std             %f2,[$out+8]
258         retl
259         xor             %o0, %o0, %o0           ! return 0
260
261 .align  16
262 .L192:
263         brz,pt          $tmp, .L192aligned
264         nop
265
266         ldd             [$inp + 24], %f6
267         faligndata      %f0, %f2, %f0
268         faligndata      %f2, %f4, %f2
269         faligndata      %f4, %f6, %f4
270
271 .L192aligned:
272         mov             12, $bits
273         and             $inc, `12*16`, $tmp
274         st              $bits, [$out + 240]     ! store rounds
275         add             $out, $tmp, $out        ! start or end of key schedule
276         sllx            $inc, 4, $inc           ! 16 or -16
277 ___
278 for ($i=0; $i<8; $i+=2) {
279     $code.=<<___;
280         std             %f0, [$out + 0]
281         faeskeyx        %f4, `0x10+$i`, %f0
282         std             %f2, [$out + 8]
283         add             $out, $inc, $out
284         faeskeyx        %f0, 0x00, %f2
285         std             %f4, [$out + 0]
286         faeskeyx        %f2, 0x00, %f4
287         std             %f0, [$out + 8]
288         add             $out, $inc, $out
289         faeskeyx        %f4, `0x10+$i+1`, %f0
290         std             %f2, [$out + 0]
291         faeskeyx        %f0, 0x00, %f2
292         std             %f4, [$out + 8]
293         add             $out, $inc, $out
294 ___
295 $code.=<<___            if ($i<6);
296         faeskeyx        %f2, 0x00, %f4
297 ___
298 }
299 $code.=<<___;
300         std             %f0, [$out + 0]
301         std             %f2, [$out + 8]
302         retl
303         xor             %o0, %o0, %o0           ! return 0
304
305 .align  16
306 .L128:
307         brz,pt          $tmp, .L128aligned
308         nop
309
310         ldd             [$inp + 16], %f4
311         faligndata      %f0, %f2, %f0
312         faligndata      %f2, %f4, %f2
313
314 .L128aligned:
315         mov             10, $bits
316         and             $inc, `10*16`, $tmp
317         st              $bits, [$out + 240]     ! store rounds
318         add             $out, $tmp, $out        ! start or end of key schedule
319         sllx            $inc, 4, $inc           ! 16 or -16
320 ___
321 for ($i=0; $i<10; $i++) {
322     $code.=<<___;
323         std             %f0, [$out + 0]
324         faeskeyx        %f2, `0x10+$i`, %f0
325         std             %f2, [$out + 8]
326         add             $out, $inc, $out
327         faeskeyx        %f0, 0x00, %f2
328 ___
329 }
330 $code.=<<___;
331         std             %f0, [$out + 0]
332         std             %f2, [$out + 8]
333         retl
334         xor             %o0, %o0, %o0           ! return 0
335 .type   aes_fx_set_encrypt_key,#function
336 .size   aes_fx_set_encrypt_key,.-aes_fx_set_encrypt_key
337 ___
338 }
339
340 # Purpose of these subroutines is to explicitly encode VIS instructions,
341 # so that one can compile the module without having to specify VIS
342 # extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a.
343 # Idea is to reserve for option to produce "universal" binary and let
344 # programmer detect if current CPU is VIS capable at run-time.
345 sub unvis {
346 my ($mnemonic,$rs1,$rs2,$rd)=@_;
347 my ($ref,$opf);
348 my %visopf = (  "faligndata"    => 0x048,
349                 "bshuffle"      => 0x04c,
350                 "fxor"          => 0x06c,
351                 "fsrc2"         => 0x078        );
352
353     $ref = "$mnemonic\t$rs1,$rs2,$rd";
354
355     if ($opf=$visopf{$mnemonic}) {
356         foreach ($rs1,$rs2,$rd) {
357             return $ref if (!/%f([0-9]{1,2})/);
358             $_=$1;
359             if ($1>=32) {
360                 return $ref if ($1&1);
361                 # re-encode for upper double register addressing
362                 $_=($1|$1>>5)&31;
363             }
364         }
365
366         return  sprintf ".word\t0x%08x !%s",
367                         0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
368                         $ref;
369     } else {
370         return $ref;
371     }
372 }
373
374 sub unvis3 {
375 my ($mnemonic,$rs1,$rs2,$rd)=@_;
376 my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 );
377 my ($ref,$opf);
378 my %visopf = (  "alignaddr"     => 0x018,
379                 "bmask"         => 0x019,
380                 "alignaddrl"    => 0x01a        );
381
382     $ref = "$mnemonic\t$rs1,$rs2,$rd";
383
384     if ($opf=$visopf{$mnemonic}) {
385         foreach ($rs1,$rs2,$rd) {
386             return $ref if (!/%([goli])([0-9])/);
387             $_=$bias{$1}+$2;
388         }
389
390         return  sprintf ".word\t0x%08x !%s",
391                         0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
392                         $ref;
393     } else {
394         return $ref;
395     }
396 }
397
398 sub unfx {
399 my ($mnemonic,$rs1,$rs2,$rd)=@_;
400 my ($ref,$opf);
401 my %aesopf = (  "faesencx"      => 0x90,
402                 "faesdecx"      => 0x91,
403                 "faesenclx"     => 0x92,
404                 "faesdeclx"     => 0x93,
405                 "faeskeyx"      => 0x94 );
406
407     $ref = "$mnemonic\t$rs1,$rs2,$rd";
408
409     if (defined($opf=$aesopf{$mnemonic})) {
410         $rs2 = ($rs2 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs2;
411         $rs2 = oct($rs2) if ($rs2 =~ /^0/);
412
413         foreach ($rs1,$rd) {
414             return $ref if (!/%f([0-9]{1,2})/);
415             $_=$1;
416             if ($1>=32) {
417                 return $ref if ($1&1);
418                 # re-encode for upper double register addressing
419                 $_=($1|$1>>5)&31;
420             }
421         }
422
423         return  sprintf ".word\t0x%08x !%s",
424                         2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
425                         $ref;
426     } else {
427         return $ref;
428     }
429 }
430
431 foreach (split("\n",$code)) {
432     s/\`([^\`]*)\`/eval $1/ge;
433
434     s/\b(faes[^x]{3,4}x)\s+(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
435                 &unfx($1,$2,$3,$4,$5)
436      /ge or
437     s/\b([fb][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
438                 &unvis($1,$2,$3,$4)
439      /ge or
440     s/\b(alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/
441                 &unvis3($1,$2,$3,$4)
442      /ge;
443     print $_,"\n";
444 }
445
446 close STDOUT;