ad61974988155beed15c27a1c27851dc98311d4e
[openssl.git] / engines / asm / e_padlock-x86_64.pl
1 #!/usr/bin/env perl
2
3 # ====================================================================
4 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
5 # project. The module is, however, dual licensed under OpenSSL and
6 # CRYPTOGAMS licenses depending on where you obtain it. For further
7 # details see http://www.openssl.org/~appro/cryptogams/.
8 # ====================================================================
9
10 # September 2011
11 #
12 # Assembler helpers for Padlock engine. See even e_padlock-x86.pl for
13 # details.
14
15 $flavour = shift;
16 $output  = shift;
17 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
18
19 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
20
21 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
22 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
23 ( $xlate="${dir}../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or
24 die "can't locate x86_64-xlate.pl";
25
26 open STDOUT,"| $^X $xlate $flavour $output";
27
28 $code=".text\n";
29
30 $PADLOCK_CHUNK=512;     # Must be a power of 2 between 32 and 2^20
31
32 $ctx="%rdx";
33 $out="%rdi";
34 $inp="%rsi";
35 $len="%rcx";
36 $chunk="%rbx";
37
38 ($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
39                                  ("%rdi","%rsi","%rdx","%rcx"); # Unix order
40
41 $code.=<<___;
42 .globl  padlock_capability
43 .type   padlock_capability,\@abi-omnipotent
44 .align  16
45 padlock_capability:
46         mov     %rbx,%r8
47         xor     %eax,%eax
48         cpuid
49         xor     %eax,%eax
50         cmp     \$`"0x".unpack("H*",'tneC')`,%ebx
51         jne     .Lnoluck
52         cmp     \$`"0x".unpack("H*",'Hrua')`,%edx
53         jne     .Lnoluck
54         cmp     \$`"0x".unpack("H*",'slua')`,%ecx
55         jne     .Lnoluck
56         mov     \$0xC0000000,%eax
57         cpuid
58         mov     %eax,%edx
59         xor     %eax,%eax
60         cmp     \$0xC0000001,%edx
61         jb      .Lnoluck
62         mov     \$0xC0000001,%eax
63         cpuid
64         mov     %edx,%eax
65         and     \$0xffffffef,%eax
66         or      \$0x10,%eax             # set Nano bit#4
67 .Lnoluck:
68         mov     %r8,%rbx
69         ret
70 .size   padlock_capability,.-padlock_capability
71
72 .globl  padlock_key_bswap
73 .type   padlock_key_bswap,\@abi-omnipotent,0
74 .align  16
75 padlock_key_bswap:
76         mov     240($arg1),%edx
77 .Lbswap_loop:
78         mov     ($arg1),%eax
79         bswap   %eax
80         mov     %eax,($arg1)
81         lea     4($arg1),$arg1
82         sub     \$1,%edx
83         jnz     .Lbswap_loop
84         ret
85 .size   padlock_key_bswap,.-padlock_key_bswap
86
87 .globl  padlock_verify_context
88 .type   padlock_verify_context,\@abi-omnipotent
89 .align  16
90 padlock_verify_context:
91         mov     $arg1,$ctx
92         pushf
93         lea     .Lpadlock_saved_context(%rip),%rax
94         call    _padlock_verify_ctx
95         lea     8(%rsp),%rsp
96         ret
97 .size   padlock_verify_context,.-padlock_verify_context
98
99 .type   _padlock_verify_ctx,\@abi-omnipotent
100 .align  16
101 _padlock_verify_ctx:
102         mov     8(%rsp),%r8
103         bt      \$30,%r8
104         jnc     .Lverified
105         cmp     (%rax),$ctx
106         je      .Lverified
107         pushf
108         popf
109 .Lverified:
110         mov     $ctx,(%rax)
111         ret
112 .size   _padlock_verify_ctx,.-_padlock_verify_ctx
113
114 .globl  padlock_reload_key
115 .type   padlock_reload_key,\@abi-omnipotent
116 .align  16
117 padlock_reload_key:
118         pushf
119         popf
120         ret
121 .size   padlock_reload_key,.-padlock_reload_key
122
123 .globl  padlock_aes_block
124 .type   padlock_aes_block,\@function,3
125 .align  16
126 padlock_aes_block:
127         mov     %rbx,%r8
128         mov     \$1,$len
129         lea     32($ctx),%rbx           # key
130         lea     16($ctx),$ctx           # control word
131         .byte   0xf3,0x0f,0xa7,0xc8     # rep xcryptecb
132         mov     %r8,%rbx
133         ret
134 .size   padlock_aes_block,.-padlock_aes_block
135
136 .globl  padlock_xstore
137 .type   padlock_xstore,\@function,2
138 .align  16
139 padlock_xstore:
140         mov     %esi,%edx
141         .byte   0x0f,0xa7,0xc0          # xstore
142         ret
143 .size   padlock_xstore,.-padlock_xstore
144
145 .globl  padlock_sha1_oneshot
146 .type   padlock_sha1_oneshot,\@function,3
147 .align  16
148 padlock_sha1_oneshot:
149         mov     %rdx,%rcx
150         mov     %rdi,%rdx               # put aside %rdi
151         movups  (%rdi),%xmm0            # copy-in context
152         sub     \$128+8,%rsp
153         mov     16(%rdi),%eax
154         movaps  %xmm0,(%rsp)
155         mov     %rsp,%rdi
156         mov     %eax,16(%rsp)
157         xor     %rax,%rax
158         .byte   0xf3,0x0f,0xa6,0xc8     # rep xsha1
159         movaps  (%rsp),%xmm0
160         mov     16(%rsp),%eax
161         movups  %xmm0,(%rdx)            # copy-out context
162         mov     %eax,16(%rdx)
163         ret
164 .size   padlock_sha1_oneshot,.-padlock_sha1_oneshot
165
166 .globl  padlock_sha1_blocks
167 .type   padlock_sha1_blocks,\@function,3
168 .align  16
169 padlock_sha1_blocks:
170         mov     %rdx,%rcx
171         mov     %rdi,%rdx               # put aside %rdi
172         movups  (%rdi),%xmm0            # copy-in context
173         sub     \$128+8,%rsp
174         mov     16(%rdi),%eax
175         movaps  %xmm0,(%rsp)
176         mov     %rsp,%rdi
177         mov     %eax,16(%rsp)
178         mov     \$-1,%rax
179         .byte   0xf3,0x0f,0xa6,0xc8     # rep xsha1
180         movaps  (%rsp),%xmm0
181         mov     16(%rsp),%eax
182         movups  %xmm0,(%rdx)            # copy-out context
183         mov     %eax,16(%rdx)
184         ret
185 .size   padlock_sha1_blocks,.-padlock_sha1_blocks
186
187 .globl  padlock_sha256_oneshot
188 .type   padlock_sha256_oneshot,\@function,3
189 .align  16
190 padlock_sha256_oneshot:
191         mov     %rdx,%rcx
192         mov     %rdi,%rdx               # put aside %rdi
193         movups  (%rdi),%xmm0            # copy-in context
194         sub     \$128+8,%rsp
195         movups  16(%rdi),%xmm1
196         movaps  %xmm0,(%rsp)
197         mov     %rsp,%rdi
198         movaps  %xmm1,16(%rsp)
199         xor     %rax,%rax
200         .byte   0xf3,0x0f,0xa6,0xd0     # rep xsha256
201         movaps  (%rsp),%xmm0
202         movaps  16(%rsp),%xmm1
203         movups  %xmm0,(%rdx)            # copy-out context
204         movups  %xmm1,16(%rdx)
205         ret
206 .size   padlock_sha256_oneshot,.-padlock_sha256_oneshot
207
208 .globl  padlock_sha256_blocks
209 .type   padlock_sha256_blocks,\@function,3
210 .align  16
211 padlock_sha256_blocks:
212         mov     %rdx,%rcx
213         mov     %rdi,%rdx               # put aside %rdi
214         movups  (%rdi),%xmm0            # copy-in context
215         sub     \$128+8,%rsp
216         movups  16(%rdi),%xmm1
217         movaps  %xmm0,(%rsp)
218         mov     %rsp,%rdi
219         movaps  %xmm1,16(%rsp)
220         mov     \$-1,%rax
221         .byte   0xf3,0x0f,0xa6,0xd0     # rep xsha256
222         movaps  (%rsp),%xmm0
223         movaps  16(%rsp),%xmm1
224         movups  %xmm0,(%rdx)            # copy-out context
225         movups  %xmm1,16(%rdx)
226         ret
227 .size   padlock_sha256_blocks,.-padlock_sha256_blocks
228
229 .globl  padlock_sha512_blocks
230 .type   padlock_sha512_blocks,\@function,3
231 .align  16
232 padlock_sha512_blocks:
233         mov     %rdx,%rcx
234         mov     %rdi,%rdx               # put aside %rdi
235         movups  (%rdi),%xmm0            # copy-in context
236         sub     \$128+8,%rsp
237         movups  16(%rdi),%xmm1
238         movups  32(%rdi),%xmm2
239         movups  48(%rdi),%xmm3
240         movaps  %xmm0,(%rsp)
241         mov     %rsp,%rdi
242         movaps  %xmm1,16(%rsp)
243         movaps  %xmm2,32(%rsp)
244         movaps  %xmm3,48(%rsp)
245         .byte   0xf3,0x0f,0xa6,0xe0     # rep xha512
246         movaps  (%rsp),%xmm0
247         movaps  16(%rsp),%xmm1
248         movaps  32(%rsp),%xmm2
249         movaps  48(%rsp),%xmm3
250         movups  %xmm0,(%rdx)            # copy-out context
251         movups  %xmm1,16(%rdx)
252         movups  %xmm2,32(%rdx)
253         movups  %xmm3,48(%rdx)
254         ret
255 .size   padlock_sha512_blocks,.-padlock_sha512_blocks
256 ___
257
258 sub generate_mode {
259 my ($mode,$opcode) = @_;
260 # int padlock_$mode_encrypt(void *out, const void *inp,
261 #               struct padlock_cipher_data *ctx, size_t len);
262 $code.=<<___;
263 .globl  padlock_${mode}_encrypt
264 .type   padlock_${mode}_encrypt,\@function,4
265 .align  16
266 padlock_${mode}_encrypt:
267         push    %rbp
268         push    %rbx
269
270         xor     %eax,%eax
271         test    \$15,$ctx
272         jnz     .L${mode}_abort
273         test    \$15,$len
274         jnz     .L${mode}_abort
275         lea     .Lpadlock_saved_context(%rip),%rax
276         pushf
277         cld
278         call    _padlock_verify_ctx
279         lea     16($ctx),$ctx           # control word
280         xor     %eax,%eax
281         xor     %ebx,%ebx
282         testl   \$`1<<5`,($ctx)         # align bit in control word
283         jnz     .L${mode}_aligned
284         test    \$0x0f,$out
285         setz    %al                     # !out_misaligned
286         test    \$0x0f,$inp
287         setz    %bl                     # !inp_misaligned
288         test    %ebx,%eax
289         jnz     .L${mode}_aligned
290         neg     %rax
291         mov     \$$PADLOCK_CHUNK,$chunk
292         not     %rax                    # out_misaligned?-1:0
293         lea     (%rsp),%rbp
294         cmp     $chunk,$len
295         cmovc   $len,$chunk             # chunk=len>PADLOCK_CHUNK?PADLOCK_CHUNK:len
296         and     $chunk,%rax             # out_misaligned?chunk:0
297         mov     $len,$chunk
298         neg     %rax
299         and     \$$PADLOCK_CHUNK-1,$chunk       # chunk%=PADLOCK_CHUNK
300         lea     (%rax,%rbp),%rsp
301 ___
302 $code.=<<___                            if ($mode eq "ctr32");
303         mov     -4($ctx),%eax           # pull 32-bit counter
304         bswap   %eax
305         neg     %eax
306         and     \$`$PADLOCK_CHUNK/16-1`,%eax
307         jz      .L${mode}_loop
308         shl     \$4,%eax
309         cmp     %rax,$len
310         cmova   %rax,$chunk             # don't let counter cross PADLOCK_CHUNK
311 ___
312 $code.=<<___;
313         jmp     .L${mode}_loop
314 .align  16
315 .L${mode}_loop:
316         cmp     $len,$chunk             # ctr32 artefact
317         cmova   $len,$chunk             # ctr32 artefact
318         mov     $out,%r8                # save parameters
319         mov     $inp,%r9
320         mov     $len,%r10
321         mov     $chunk,$len
322         mov     $chunk,%r11
323         test    \$0x0f,$out             # out_misaligned
324         cmovnz  %rsp,$out
325         test    \$0x0f,$inp             # inp_misaligned
326         jz      .L${mode}_inp_aligned
327         shr     \$3,$len
328         .byte   0xf3,0x48,0xa5          # rep movsq
329         sub     $chunk,$out
330         mov     $chunk,$len
331         mov     $out,$inp
332 .L${mode}_inp_aligned:
333         lea     -16($ctx),%rax          # ivp
334         lea     16($ctx),%rbx           # key
335         shr     \$4,$len
336         .byte   0xf3,0x0f,0xa7,$opcode  # rep xcrypt*
337 ___
338 $code.=<<___                            if ($mode !~ /ecb|ctr/);
339         movdqa  (%rax),%xmm0
340         movdqa  %xmm0,-16($ctx)         # copy [or refresh] iv
341 ___
342 $code.=<<___                            if ($mode eq "ctr32");
343         mov     -4($ctx),%eax           # pull 32-bit counter
344         test    \$0xffff0000,%eax
345         jnz     .L${mode}_no_corr
346         bswap   %eax
347         add     \$0x10000,%eax
348         bswap   %eax
349         mov     %eax,-4($ctx)
350 .L${mode}_no_corr:
351 ___
352 $code.=<<___;
353         mov     %r8,$out                # restore paramters
354         mov     %r11,$chunk
355         test    \$0x0f,$out
356         jz      .L${mode}_out_aligned
357         mov     $chunk,$len
358         shr     \$3,$len
359         lea     (%rsp),$inp
360         .byte   0xf3,0x48,0xa5          # rep movsq
361         sub     $chunk,$out
362 .L${mode}_out_aligned:
363         mov     %r9,$inp
364         mov     %r10,$len
365         add     $chunk,$out
366         add     $chunk,$inp
367         sub     $chunk,$len
368         mov     \$$PADLOCK_CHUNK,$chunk
369         jnz     .L${mode}_loop
370
371         test    \$0x0f,$out
372         jz      .L${mode}_done
373
374         mov     %rbp,$len
375         mov     %rsp,$out
376         sub     %rsp,$len
377         xor     %rax,%rax
378         shr     \$3,$len
379         .byte   0xf3,0x48,0xab          # rep stosq
380 .L${mode}_done:
381         lea     (%rbp),%rsp
382         jmp     .L${mode}_exit
383
384 .align  16
385 .L${mode}_aligned:
386 ___
387 $code.=<<___                            if ($mode eq "ctr32");
388         mov     -4($ctx),%eax           # pull 32-bit counter
389         mov     \$`16*0x10000`,$chunk
390         bswap   %eax
391         cmp     $len,$chunk
392         cmova   $len,$chunk
393         neg     %eax
394         and     \$0xffff,%eax
395         jz      .L${mode}_aligned_loop
396         shl     \$4,%eax
397         cmp     %rax,$len
398         cmova   %rax,$chunk             # don't let counter cross 2^16
399         jmp     .L${mode}_aligned_loop
400 .align  16
401 .L${mode}_aligned_loop:
402         cmp     $len,$chunk
403         cmova   $len,$chunk
404         mov     $len,%r10               # save parameters
405         mov     $chunk,$len
406         mov     $chunk,%r11
407 ___
408 $code.=<<___;
409         lea     -16($ctx),%rax          # ivp
410         lea     16($ctx),%rbx           # key
411         shr     \$4,$len                # len/=AES_BLOCK_SIZE
412         .byte   0xf3,0x0f,0xa7,$opcode  # rep xcrypt*
413 ___
414 $code.=<<___                            if ($mode !~ /ecb|ctr/);
415         movdqa  (%rax),%xmm0
416         movdqa  %xmm0,-16($ctx)         # copy [or refresh] iv
417 ___
418 $code.=<<___                            if ($mode eq "ctr32");
419         mov     -4($ctx),%eax           # pull 32-bit counter
420         bswap   %eax
421         add     \$0x10000,%eax
422         bswap   %eax
423         mov     %eax,-4($ctx)
424
425         mov     %r11,$chunk             # restore paramters
426         mov     %r10,$len
427         sub     $chunk,$len
428         mov     \$`16*0x10000`,$chunk
429         jnz     .L${mode}_aligned_loop
430 ___
431 $code.=<<___;
432 .L${mode}_exit:
433         mov     \$1,%eax
434         lea     8(%rsp),%rsp
435 .L${mode}_abort:
436         pop     %rbx
437         pop     %rbp
438         ret
439 .size   padlock_${mode}_encrypt,.-padlock_${mode}_encrypt
440 ___
441 }
442
443 &generate_mode("ecb",0xc8);
444 &generate_mode("cbc",0xd0);
445 &generate_mode("cfb",0xe0);
446 &generate_mode("ofb",0xe8);
447 &generate_mode("ctr32",0xd8);   # all 64-bit CPUs have working CTR...
448
449 $code.=<<___;
450 .asciz  "VIA Padlock x86_64 module, CRYPTOGAMS by <appro\@openssl.org>"
451 .align  16
452 .data
453 .align  8
454 .Lpadlock_saved_context:
455         .quad   0
456 ___
457 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
458
459 print $code;
460
461 close STDOUT;