1b88026f08ecbb65ae72ee7ecf305578183525c1
[openssl.git] / crypto / bn / asm / rsaz-x86_64.pl
1 #! /usr/bin/env perl
2 # Copyright 2013-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 #                                                                            #
12 #  Copyright (c) 2012, Intel Corporation                                     #
13 #                                                                            #
14 #  All rights reserved.                                                      #
15 #                                                                            #
16 #  Redistribution and use in source and binary forms, with or without        #
17 #  modification, are permitted provided that the following conditions are    #
18 #  met:                                                                      #
19 #                                                                            #
20 #  *  Redistributions of source code must retain the above copyright         #
21 #     notice, this list of conditions and the following disclaimer.          #
22 #                                                                            #
23 #  *  Redistributions in binary form must reproduce the above copyright      #
24 #     notice, this list of conditions and the following disclaimer in the    #
25 #     documentation and/or other materials provided with the                 #
26 #     distribution.                                                          #
27 #                                                                            #
28 #  *  Neither the name of the Intel Corporation nor the names of its         #
29 #     contributors may be used to endorse or promote products derived from   #
30 #     this software without specific prior written permission.               #
31 #                                                                            #
32 #                                                                            #
33 #  THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY          #
34 #  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE         #
35 #  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        #
36 #  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR            #
37 #  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
38 #  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       #
39 #  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        #
40 #  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    #
41 #  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      #
42 #  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        #
43 #  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              #
44 #                                                                            #
45 ##############################################################################
46 # Developers and authors:                                                    #
47 # Shay Gueron (1, 2), and Vlad Krasnov (1)                                   #
48 # (1) Intel Architecture Group, Microprocessor and Chipset Development,      #
49 #     Israel Development Center, Haifa, Israel                               #
50 # (2) University of Haifa                                                    #
51 ##############################################################################
52 # Reference:                                                                 #
53 # [1] S. Gueron, "Efficient Software Implementations of Modular              #
54 #     Exponentiation", http://eprint.iacr.org/2011/239                       #
55 # [2] S. Gueron, V. Krasnov. "Speeding up Big-Numbers Squaring".             #
56 #     IEEE Proceedings of 9th International Conference on Information        #
57 #     Technology: New Generations (ITNG 2012), 821-823 (2012).               #
58 # [3] S. Gueron, Efficient Software Implementations of Modular Exponentiation#
59 #     Journal of Cryptographic Engineering 2:31-43 (2012).                   #
60 # [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis    #
61 #     resistant 512-bit and 1024-bit modular exponentiation for optimizing   #
62 #     RSA1024 and RSA2048 on x86_64 platforms",                              #
63 #     http://rt.openssl.org/Ticket/Display.html?id=2582&user=guest&pass=guest#
64 ##############################################################################
65
66 # While original submission covers 512- and 1024-bit exponentiation,
67 # this module is limited to 512-bit version only (and as such
68 # accelerates RSA1024 sign). This is because improvement for longer
69 # keys is not high enough to justify the effort, highest measured
70 # was ~5% on Westmere. [This is relative to OpenSSL 1.0.2, upcoming
71 # for the moment of this writing!] Nor does this module implement
72 # "monolithic" complete exponentiation jumbo-subroutine, but adheres
73 # to more modular mixture of C and assembly. And it's optimized even
74 # for processors other than Intel Core family (see table below for
75 # improvement coefficients).
76 #                                               <appro@openssl.org>
77 #
78 # RSA1024 sign/sec      this/original   |this/rsax(*)   this/fips(*)
79 #                       ----------------+---------------------------
80 # Opteron               +13%            |+5%            +20%
81 # Bulldozer             -0%             |-1%            +10%
82 # P4                    +11%            |+7%            +8%
83 # Westmere              +5%             |+14%           +17%
84 # Sandy Bridge          +2%             |+12%           +29%
85 # Ivy Bridge            +1%             |+11%           +35%
86 # Haswell(**)           -0%             |+12%           +39%
87 # Atom                  +13%            |+11%           +4%
88 # VIA Nano              +70%            |+9%            +25%
89 #
90 # (*)   rsax engine and fips numbers are presented for reference
91 #       purposes;
92 # (**)  MULX was attempted, but found to give only marginal improvement;
93
94 $flavour = shift;
95 $output  = shift;
96 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
97
98 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
99
100 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
101 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
102 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
103 die "can't locate x86_64-xlate.pl";
104
105 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
106 *STDOUT=*OUT;
107
108 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
109                 =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
110         $addx = ($1>=2.23);
111 }
112
113 if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
114             `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
115         $addx = ($1>=2.10);
116 }
117
118 if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
119             `ml64 2>&1` =~ /Version ([0-9]+)\./) {
120         $addx = ($1>=12);
121 }
122
123 if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) {
124         my $ver = $2 + $3/100.0;        # 3.1->3.01, 3.10->3.10
125         $addx = ($ver>=3.03);
126 }
127
128 ($out, $inp, $mod) = ("%rdi", "%rsi", "%rbp");  # common internal API
129 {
130 my ($out,$inp,$mod,$n0,$times) = ("%rdi","%rsi","%rdx","%rcx","%r8d");
131
132 $code.=<<___;
133 .text
134
135 .extern OPENSSL_ia32cap_P
136
137 .globl  rsaz_512_sqr
138 .type   rsaz_512_sqr,\@function,5
139 .align  32
140 rsaz_512_sqr:                           # 25-29% faster than rsaz_512_mul
141 .cfi_startproc
142         push    %rbx
143 .cfi_push       %rbx
144         push    %rbp
145 .cfi_push       %rbp
146         push    %r12
147 .cfi_push       %r12
148         push    %r13
149 .cfi_push       %r13
150         push    %r14
151 .cfi_push       %r14
152         push    %r15
153 .cfi_push       %r15
154
155         subq    \$128+24, %rsp
156 .cfi_adjust_cfa_offset  128+24
157 .Lsqr_body:
158         movq    $mod, %rbp              # common argument
159         movq    ($inp), %rdx
160         movq    8($inp), %rax
161         movq    $n0, 128(%rsp)
162 ___
163 $code.=<<___ if ($addx);
164         movl    \$0x80100,%r11d
165         andl    OPENSSL_ia32cap_P+8(%rip),%r11d
166         cmpl    \$0x80100,%r11d         # check for MULX and ADO/CX
167         je      .Loop_sqrx
168 ___
169 $code.=<<___;
170         jmp     .Loop_sqr
171
172 .align  32
173 .Loop_sqr:
174         movl    $times,128+8(%rsp)
175 #first iteration
176         movq    %rdx, %rbx
177         mulq    %rdx
178         movq    %rax, %r8
179         movq    16($inp), %rax
180         movq    %rdx, %r9
181
182         mulq    %rbx
183         addq    %rax, %r9
184         movq    24($inp), %rax
185         movq    %rdx, %r10
186         adcq    \$0, %r10
187
188         mulq    %rbx
189         addq    %rax, %r10
190         movq    32($inp), %rax
191         movq    %rdx, %r11
192         adcq    \$0, %r11
193
194         mulq    %rbx
195         addq    %rax, %r11
196         movq    40($inp), %rax
197         movq    %rdx, %r12
198         adcq    \$0, %r12
199
200         mulq    %rbx
201         addq    %rax, %r12
202         movq    48($inp), %rax
203         movq    %rdx, %r13
204         adcq    \$0, %r13
205
206         mulq    %rbx
207         addq    %rax, %r13
208         movq    56($inp), %rax
209         movq    %rdx, %r14
210         adcq    \$0, %r14
211
212         mulq    %rbx
213         addq    %rax, %r14
214         movq    %rbx, %rax
215         movq    %rdx, %r15
216         adcq    \$0, %r15
217
218         addq    %r8, %r8                #shlq   \$1, %r8
219         movq    %r9, %rcx
220         adcq    %r9, %r9                #shld   \$1, %r8, %r9
221
222         mulq    %rax
223         movq    %rax, (%rsp)
224         addq    %rdx, %r8
225         adcq    \$0, %r9
226
227         movq    %r8, 8(%rsp)
228         shrq    \$63, %rcx
229
230 #second iteration
231         movq    8($inp), %r8
232         movq    16($inp), %rax
233         mulq    %r8
234         addq    %rax, %r10
235         movq    24($inp), %rax
236         movq    %rdx, %rbx
237         adcq    \$0, %rbx
238
239         mulq    %r8
240         addq    %rax, %r11
241         movq    32($inp), %rax
242         adcq    \$0, %rdx
243         addq    %rbx, %r11
244         movq    %rdx, %rbx
245         adcq    \$0, %rbx
246
247         mulq    %r8
248         addq    %rax, %r12
249         movq    40($inp), %rax
250         adcq    \$0, %rdx
251         addq    %rbx, %r12
252         movq    %rdx, %rbx
253         adcq    \$0, %rbx
254
255         mulq    %r8
256         addq    %rax, %r13
257         movq    48($inp), %rax
258         adcq    \$0, %rdx
259         addq    %rbx, %r13
260         movq    %rdx, %rbx
261         adcq    \$0, %rbx
262
263         mulq    %r8
264         addq    %rax, %r14
265         movq    56($inp), %rax
266         adcq    \$0, %rdx
267         addq    %rbx, %r14
268         movq    %rdx, %rbx
269         adcq    \$0, %rbx
270
271         mulq    %r8
272         addq    %rax, %r15
273         movq    %r8, %rax
274         adcq    \$0, %rdx
275         addq    %rbx, %r15
276         movq    %rdx, %r8
277         movq    %r10, %rdx
278         adcq    \$0, %r8
279
280         add     %rdx, %rdx
281         lea     (%rcx,%r10,2), %r10     #shld   \$1, %rcx, %r10
282         movq    %r11, %rbx
283         adcq    %r11, %r11              #shld   \$1, %r10, %r11
284
285         mulq    %rax
286         addq    %rax, %r9
287         adcq    %rdx, %r10
288         adcq    \$0, %r11
289
290         movq    %r9, 16(%rsp)
291         movq    %r10, 24(%rsp)
292         shrq    \$63, %rbx
293
294 #third iteration
295         movq    16($inp), %r9
296         movq    24($inp), %rax
297         mulq    %r9
298         addq    %rax, %r12
299         movq    32($inp), %rax
300         movq    %rdx, %rcx
301         adcq    \$0, %rcx
302
303         mulq    %r9
304         addq    %rax, %r13
305         movq    40($inp), %rax
306         adcq    \$0, %rdx
307         addq    %rcx, %r13
308         movq    %rdx, %rcx
309         adcq    \$0, %rcx
310
311         mulq    %r9
312         addq    %rax, %r14
313         movq    48($inp), %rax
314         adcq    \$0, %rdx
315         addq    %rcx, %r14
316         movq    %rdx, %rcx
317         adcq    \$0, %rcx
318
319         mulq    %r9
320          movq   %r12, %r10
321          lea    (%rbx,%r12,2), %r12     #shld   \$1, %rbx, %r12
322         addq    %rax, %r15
323         movq    56($inp), %rax
324         adcq    \$0, %rdx
325         addq    %rcx, %r15
326         movq    %rdx, %rcx
327         adcq    \$0, %rcx
328
329         mulq    %r9
330          shrq   \$63, %r10
331         addq    %rax, %r8
332         movq    %r9, %rax
333         adcq    \$0, %rdx
334         addq    %rcx, %r8
335         movq    %rdx, %r9
336         adcq    \$0, %r9
337
338         movq    %r13, %rcx
339         leaq    (%r10,%r13,2), %r13     #shld   \$1, %r12, %r13
340
341         mulq    %rax
342         addq    %rax, %r11
343         adcq    %rdx, %r12
344         adcq    \$0, %r13
345
346         movq    %r11, 32(%rsp)
347         movq    %r12, 40(%rsp)
348         shrq    \$63, %rcx
349
350 #fourth iteration
351         movq    24($inp), %r10
352         movq    32($inp), %rax
353         mulq    %r10
354         addq    %rax, %r14
355         movq    40($inp), %rax
356         movq    %rdx, %rbx
357         adcq    \$0, %rbx
358
359         mulq    %r10
360         addq    %rax, %r15
361         movq    48($inp), %rax
362         adcq    \$0, %rdx
363         addq    %rbx, %r15
364         movq    %rdx, %rbx
365         adcq    \$0, %rbx
366
367         mulq    %r10
368          movq   %r14, %r12
369          leaq   (%rcx,%r14,2), %r14     #shld   \$1, %rcx, %r14
370         addq    %rax, %r8
371         movq    56($inp), %rax
372         adcq    \$0, %rdx
373         addq    %rbx, %r8
374         movq    %rdx, %rbx
375         adcq    \$0, %rbx
376
377         mulq    %r10
378          shrq   \$63, %r12
379         addq    %rax, %r9
380         movq    %r10, %rax
381         adcq    \$0, %rdx
382         addq    %rbx, %r9
383         movq    %rdx, %r10
384         adcq    \$0, %r10
385
386         movq    %r15, %rbx
387         leaq    (%r12,%r15,2),%r15      #shld   \$1, %r14, %r15
388
389         mulq    %rax
390         addq    %rax, %r13
391         adcq    %rdx, %r14
392         adcq    \$0, %r15
393
394         movq    %r13, 48(%rsp)
395         movq    %r14, 56(%rsp)
396         shrq    \$63, %rbx
397
398 #fifth iteration
399         movq    32($inp), %r11
400         movq    40($inp), %rax
401         mulq    %r11
402         addq    %rax, %r8
403         movq    48($inp), %rax
404         movq    %rdx, %rcx
405         adcq    \$0, %rcx
406
407         mulq    %r11
408         addq    %rax, %r9
409         movq    56($inp), %rax
410         adcq    \$0, %rdx
411          movq   %r8, %r12
412          leaq   (%rbx,%r8,2), %r8       #shld   \$1, %rbx, %r8
413         addq    %rcx, %r9
414         movq    %rdx, %rcx
415         adcq    \$0, %rcx
416
417         mulq    %r11
418          shrq   \$63, %r12
419         addq    %rax, %r10
420         movq    %r11, %rax
421         adcq    \$0, %rdx
422         addq    %rcx, %r10
423         movq    %rdx, %r11
424         adcq    \$0, %r11
425
426         movq    %r9, %rcx
427         leaq    (%r12,%r9,2), %r9       #shld   \$1, %r8, %r9
428
429         mulq    %rax
430         addq    %rax, %r15
431         adcq    %rdx, %r8
432         adcq    \$0, %r9
433
434         movq    %r15, 64(%rsp)
435         movq    %r8, 72(%rsp)
436         shrq    \$63, %rcx
437
438 #sixth iteration
439         movq    40($inp), %r12
440         movq    48($inp), %rax
441         mulq    %r12
442         addq    %rax, %r10
443         movq    56($inp), %rax
444         movq    %rdx, %rbx
445         adcq    \$0, %rbx
446
447         mulq    %r12
448         addq    %rax, %r11
449         movq    %r12, %rax
450          movq   %r10, %r15
451          leaq   (%rcx,%r10,2), %r10     #shld   \$1, %rcx, %r10
452         adcq    \$0, %rdx
453          shrq   \$63, %r15
454         addq    %rbx, %r11
455         movq    %rdx, %r12
456         adcq    \$0, %r12
457
458         movq    %r11, %rbx
459         leaq    (%r15,%r11,2), %r11     #shld   \$1, %r10, %r11
460
461         mulq    %rax
462         addq    %rax, %r9
463         adcq    %rdx, %r10
464         adcq    \$0, %r11
465
466         movq    %r9, 80(%rsp)
467         movq    %r10, 88(%rsp)
468
469 #seventh iteration
470         movq    48($inp), %r13
471         movq    56($inp), %rax
472         mulq    %r13
473         addq    %rax, %r12
474         movq    %r13, %rax
475         movq    %rdx, %r13
476         adcq    \$0, %r13
477
478         xorq    %r14, %r14
479         shlq    \$1, %rbx
480         adcq    %r12, %r12              #shld   \$1, %rbx, %r12
481         adcq    %r13, %r13              #shld   \$1, %r12, %r13
482         adcq    %r14, %r14              #shld   \$1, %r13, %r14
483
484         mulq    %rax
485         addq    %rax, %r11
486         adcq    %rdx, %r12
487         adcq    \$0, %r13
488
489         movq    %r11, 96(%rsp)
490         movq    %r12, 104(%rsp)
491
492 #eighth iteration
493         movq    56($inp), %rax
494         mulq    %rax
495         addq    %rax, %r13
496         adcq    \$0, %rdx
497
498         addq    %rdx, %r14
499
500         movq    %r13, 112(%rsp)
501         movq    %r14, 120(%rsp)
502
503         movq    (%rsp), %r8
504         movq    8(%rsp), %r9
505         movq    16(%rsp), %r10
506         movq    24(%rsp), %r11
507         movq    32(%rsp), %r12
508         movq    40(%rsp), %r13
509         movq    48(%rsp), %r14
510         movq    56(%rsp), %r15
511
512         call    __rsaz_512_reduce
513
514         addq    64(%rsp), %r8
515         adcq    72(%rsp), %r9
516         adcq    80(%rsp), %r10
517         adcq    88(%rsp), %r11
518         adcq    96(%rsp), %r12
519         adcq    104(%rsp), %r13
520         adcq    112(%rsp), %r14
521         adcq    120(%rsp), %r15
522         sbbq    %rcx, %rcx
523
524         call    __rsaz_512_subtract
525
526         movq    %r8, %rdx
527         movq    %r9, %rax
528         movl    128+8(%rsp), $times
529         movq    $out, $inp
530
531         decl    $times
532         jnz     .Loop_sqr
533 ___
534 if ($addx) {
535 $code.=<<___;
536         jmp     .Lsqr_tail
537
538 .align  32
539 .Loop_sqrx:
540         movl    $times,128+8(%rsp)
541         movq    $out, %xmm0             # off-load
542         movq    %rbp, %xmm1             # off-load
543 #first iteration
544         mulx    %rax, %r8, %r9
545
546         mulx    16($inp), %rcx, %r10
547         xor     %rbp, %rbp              # cf=0, of=0
548
549         mulx    24($inp), %rax, %r11
550         adcx    %rcx, %r9
551
552         mulx    32($inp), %rcx, %r12
553         adcx    %rax, %r10
554
555         mulx    40($inp), %rax, %r13
556         adcx    %rcx, %r11
557
558         .byte   0xc4,0x62,0xf3,0xf6,0xb6,0x30,0x00,0x00,0x00    # mulx  48($inp), %rcx, %r14
559         adcx    %rax, %r12
560         adcx    %rcx, %r13
561
562         .byte   0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00    # mulx  56($inp), %rax, %r15
563         adcx    %rax, %r14
564         adcx    %rbp, %r15              # %rbp is 0
565
566         mov     %r9, %rcx
567         shld    \$1, %r8, %r9
568         shl     \$1, %r8
569
570         xor     %ebp, %ebp
571         mulx    %rdx, %rax, %rdx
572         adcx    %rdx, %r8
573          mov    8($inp), %rdx
574         adcx    %rbp, %r9
575
576         mov     %rax, (%rsp)
577         mov     %r8, 8(%rsp)
578
579 #second iteration
580         mulx    16($inp), %rax, %rbx
581         adox    %rax, %r10
582         adcx    %rbx, %r11
583
584         .byte   0xc4,0x62,0xc3,0xf6,0x86,0x18,0x00,0x00,0x00    # mulx  24($inp), $out, %r8
585         adox    $out, %r11
586         adcx    %r8, %r12
587
588         mulx    32($inp), %rax, %rbx
589         adox    %rax, %r12
590         adcx    %rbx, %r13
591
592         mulx    40($inp), $out, %r8
593         adox    $out, %r13
594         adcx    %r8, %r14
595
596         .byte   0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00    # mulx  48($inp), %rax, %rbx
597         adox    %rax, %r14
598         adcx    %rbx, %r15
599
600         .byte   0xc4,0x62,0xc3,0xf6,0x86,0x38,0x00,0x00,0x00    # mulx  56($inp), $out, %r8
601         adox    $out, %r15
602         adcx    %rbp, %r8
603         adox    %rbp, %r8
604
605         mov     %r11, %rbx
606         shld    \$1, %r10, %r11
607         shld    \$1, %rcx, %r10
608
609         xor     %ebp,%ebp
610         mulx    %rdx, %rax, %rcx
611          mov    16($inp), %rdx
612         adcx    %rax, %r9
613         adcx    %rcx, %r10
614         adcx    %rbp, %r11
615
616         mov     %r9, 16(%rsp)
617         .byte   0x4c,0x89,0x94,0x24,0x18,0x00,0x00,0x00         # mov   %r10, 24(%rsp)
618
619 #third iteration
620         .byte   0xc4,0x62,0xc3,0xf6,0x8e,0x18,0x00,0x00,0x00    # mulx  24($inp), $out, %r9
621         adox    $out, %r12
622         adcx    %r9, %r13
623
624         mulx    32($inp), %rax, %rcx
625         adox    %rax, %r13
626         adcx    %rcx, %r14
627
628         mulx    40($inp), $out, %r9
629         adox    $out, %r14
630         adcx    %r9, %r15
631
632         .byte   0xc4,0xe2,0xfb,0xf6,0x8e,0x30,0x00,0x00,0x00    # mulx  48($inp), %rax, %rcx
633         adox    %rax, %r15
634         adcx    %rcx, %r8
635
636         .byte   0xc4,0x62,0xc3,0xf6,0x8e,0x38,0x00,0x00,0x00    # mulx  56($inp), $out, %r9
637         adox    $out, %r8
638         adcx    %rbp, %r9
639         adox    %rbp, %r9
640
641         mov     %r13, %rcx
642         shld    \$1, %r12, %r13
643         shld    \$1, %rbx, %r12
644
645         xor     %ebp, %ebp
646         mulx    %rdx, %rax, %rdx
647         adcx    %rax, %r11
648         adcx    %rdx, %r12
649          mov    24($inp), %rdx
650         adcx    %rbp, %r13
651
652         mov     %r11, 32(%rsp)
653         .byte   0x4c,0x89,0xa4,0x24,0x28,0x00,0x00,0x00         # mov   %r12, 40(%rsp)
654
655 #fourth iteration
656         .byte   0xc4,0xe2,0xfb,0xf6,0x9e,0x20,0x00,0x00,0x00    # mulx  32($inp), %rax, %rbx
657         adox    %rax, %r14
658         adcx    %rbx, %r15
659
660         mulx    40($inp), $out, %r10
661         adox    $out, %r15
662         adcx    %r10, %r8
663
664         mulx    48($inp), %rax, %rbx
665         adox    %rax, %r8
666         adcx    %rbx, %r9
667
668         mulx    56($inp), $out, %r10
669         adox    $out, %r9
670         adcx    %rbp, %r10
671         adox    %rbp, %r10
672
673         .byte   0x66
674         mov     %r15, %rbx
675         shld    \$1, %r14, %r15
676         shld    \$1, %rcx, %r14
677
678         xor     %ebp, %ebp
679         mulx    %rdx, %rax, %rdx
680         adcx    %rax, %r13
681         adcx    %rdx, %r14
682          mov    32($inp), %rdx
683         adcx    %rbp, %r15
684
685         mov     %r13, 48(%rsp)
686         mov     %r14, 56(%rsp)
687
688 #fifth iteration
689         .byte   0xc4,0x62,0xc3,0xf6,0x9e,0x28,0x00,0x00,0x00    # mulx  40($inp), $out, %r11
690         adox    $out, %r8
691         adcx    %r11, %r9
692
693         mulx    48($inp), %rax, %rcx
694         adox    %rax, %r9
695         adcx    %rcx, %r10
696
697         mulx    56($inp), $out, %r11
698         adox    $out, %r10
699         adcx    %rbp, %r11
700         adox    %rbp, %r11
701
702         mov     %r9, %rcx
703         shld    \$1, %r8, %r9
704         shld    \$1, %rbx, %r8
705
706         xor     %ebp, %ebp
707         mulx    %rdx, %rax, %rdx
708         adcx    %rax, %r15
709         adcx    %rdx, %r8
710          mov    40($inp), %rdx
711         adcx    %rbp, %r9
712
713         mov     %r15, 64(%rsp)
714         mov     %r8, 72(%rsp)
715
716 #sixth iteration
717         .byte   0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00    # mulx  48($inp), %rax, %rbx
718         adox    %rax, %r10
719         adcx    %rbx, %r11
720
721         .byte   0xc4,0x62,0xc3,0xf6,0xa6,0x38,0x00,0x00,0x00    # mulx  56($inp), $out, %r12
722         adox    $out, %r11
723         adcx    %rbp, %r12
724         adox    %rbp, %r12
725
726         mov     %r11, %rbx
727         shld    \$1, %r10, %r11
728         shld    \$1, %rcx, %r10
729
730         xor     %ebp, %ebp
731         mulx    %rdx, %rax, %rdx
732         adcx    %rax, %r9
733         adcx    %rdx, %r10
734          mov    48($inp), %rdx
735         adcx    %rbp, %r11
736
737         mov     %r9, 80(%rsp)
738         mov     %r10, 88(%rsp)
739
740 #seventh iteration
741         .byte   0xc4,0x62,0xfb,0xf6,0xae,0x38,0x00,0x00,0x00    # mulx  56($inp), %rax, %r13
742         adox    %rax, %r12
743         adox    %rbp, %r13
744
745         xor     %r14, %r14
746         shld    \$1, %r13, %r14
747         shld    \$1, %r12, %r13
748         shld    \$1, %rbx, %r12
749
750         xor     %ebp, %ebp
751         mulx    %rdx, %rax, %rdx
752         adcx    %rax, %r11
753         adcx    %rdx, %r12
754          mov    56($inp), %rdx
755         adcx    %rbp, %r13
756
757         .byte   0x4c,0x89,0x9c,0x24,0x60,0x00,0x00,0x00         # mov   %r11, 96(%rsp)
758         .byte   0x4c,0x89,0xa4,0x24,0x68,0x00,0x00,0x00         # mov   %r12, 104(%rsp)
759
760 #eighth iteration
761         mulx    %rdx, %rax, %rdx
762         adox    %rax, %r13
763         adox    %rbp, %rdx
764
765         .byte   0x66
766         add     %rdx, %r14
767
768         movq    %r13, 112(%rsp)
769         movq    %r14, 120(%rsp)
770         movq    %xmm0, $out
771         movq    %xmm1, %rbp
772
773         movq    128(%rsp), %rdx         # pull $n0
774         movq    (%rsp), %r8
775         movq    8(%rsp), %r9
776         movq    16(%rsp), %r10
777         movq    24(%rsp), %r11
778         movq    32(%rsp), %r12
779         movq    40(%rsp), %r13
780         movq    48(%rsp), %r14
781         movq    56(%rsp), %r15
782
783         call    __rsaz_512_reducex
784
785         addq    64(%rsp), %r8
786         adcq    72(%rsp), %r9
787         adcq    80(%rsp), %r10
788         adcq    88(%rsp), %r11
789         adcq    96(%rsp), %r12
790         adcq    104(%rsp), %r13
791         adcq    112(%rsp), %r14
792         adcq    120(%rsp), %r15
793         sbbq    %rcx, %rcx
794
795         call    __rsaz_512_subtract
796
797         movq    %r8, %rdx
798         movq    %r9, %rax
799         movl    128+8(%rsp), $times
800         movq    $out, $inp
801
802         decl    $times
803         jnz     .Loop_sqrx
804
805 .Lsqr_tail:
806 ___
807 }
808 $code.=<<___;
809
810         leaq    128+24+48(%rsp), %rax
811 .cfi_def_cfa    %rax,8
812         movq    -48(%rax), %r15
813 .cfi_restore    %r15
814         movq    -40(%rax), %r14
815 .cfi_restore    %r14
816         movq    -32(%rax), %r13
817 .cfi_restore    %r13
818         movq    -24(%rax), %r12
819 .cfi_restore    %r12
820         movq    -16(%rax), %rbp
821 .cfi_restore    %rbp
822         movq    -8(%rax), %rbx
823 .cfi_restore    %rbx
824         leaq    (%rax), %rsp
825 .cfi_def_cfa_register   %rsp
826 .Lsqr_epilogue:
827         ret
828 .cfi_endproc
829 .size   rsaz_512_sqr,.-rsaz_512_sqr
830 ___
831 }
832 {
833 my ($out,$ap,$bp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx","%r8");
834 $code.=<<___;
835 .globl  rsaz_512_mul
836 .type   rsaz_512_mul,\@function,5
837 .align  32
838 rsaz_512_mul:
839 .cfi_startproc
840         push    %rbx
841 .cfi_push       %rbx
842         push    %rbp
843 .cfi_push       %rbp
844         push    %r12
845 .cfi_push       %r12
846         push    %r13
847 .cfi_push       %r13
848         push    %r14
849 .cfi_push       %r14
850         push    %r15
851 .cfi_push       %r15
852
853         subq    \$128+24, %rsp
854 .cfi_adjust_cfa_offset  128+24
855 .Lmul_body:
856         movq    $out, %xmm0             # off-load arguments
857         movq    $mod, %xmm1
858         movq    $n0, 128(%rsp)
859 ___
860 $code.=<<___ if ($addx);
861         movl    \$0x80100,%r11d
862         andl    OPENSSL_ia32cap_P+8(%rip),%r11d
863         cmpl    \$0x80100,%r11d         # check for MULX and ADO/CX
864         je      .Lmulx
865 ___
866 $code.=<<___;
867         movq    ($bp), %rbx             # pass b[0]
868         movq    $bp, %rbp               # pass argument
869         call    __rsaz_512_mul
870
871         movq    %xmm0, $out
872         movq    %xmm1, %rbp
873
874         movq    (%rsp), %r8
875         movq    8(%rsp), %r9
876         movq    16(%rsp), %r10
877         movq    24(%rsp), %r11
878         movq    32(%rsp), %r12
879         movq    40(%rsp), %r13
880         movq    48(%rsp), %r14
881         movq    56(%rsp), %r15
882
883         call    __rsaz_512_reduce
884 ___
885 $code.=<<___ if ($addx);
886         jmp     .Lmul_tail
887
888 .align  32
889 .Lmulx:
890         movq    $bp, %rbp               # pass argument
891         movq    ($bp), %rdx             # pass b[0]
892         call    __rsaz_512_mulx
893
894         movq    %xmm0, $out
895         movq    %xmm1, %rbp
896
897         movq    128(%rsp), %rdx         # pull $n0
898         movq    (%rsp), %r8
899         movq    8(%rsp), %r9
900         movq    16(%rsp), %r10
901         movq    24(%rsp), %r11
902         movq    32(%rsp), %r12
903         movq    40(%rsp), %r13
904         movq    48(%rsp), %r14
905         movq    56(%rsp), %r15
906
907         call    __rsaz_512_reducex
908 .Lmul_tail:
909 ___
910 $code.=<<___;
911         addq    64(%rsp), %r8
912         adcq    72(%rsp), %r9
913         adcq    80(%rsp), %r10
914         adcq    88(%rsp), %r11
915         adcq    96(%rsp), %r12
916         adcq    104(%rsp), %r13
917         adcq    112(%rsp), %r14
918         adcq    120(%rsp), %r15
919         sbbq    %rcx, %rcx
920
921         call    __rsaz_512_subtract
922
923         leaq    128+24+48(%rsp), %rax
924 .cfi_def_cfa    %rax,8
925         movq    -48(%rax), %r15
926 .cfi_restore    %r15
927         movq    -40(%rax), %r14
928 .cfi_restore    %r14
929         movq    -32(%rax), %r13
930 .cfi_restore    %r13
931         movq    -24(%rax), %r12
932 .cfi_restore    %r12
933         movq    -16(%rax), %rbp
934 .cfi_restore    %rbp
935         movq    -8(%rax), %rbx
936 .cfi_restore    %rbx
937         leaq    (%rax), %rsp
938 .cfi_def_cfa_register   %rsp
939 .Lmul_epilogue:
940         ret
941 .cfi_endproc
942 .size   rsaz_512_mul,.-rsaz_512_mul
943 ___
944 }
945 {
946 my ($out,$ap,$bp,$mod,$n0,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
947 $code.=<<___;
948 .globl  rsaz_512_mul_gather4
949 .type   rsaz_512_mul_gather4,\@function,6
950 .align  32
951 rsaz_512_mul_gather4:
952 .cfi_startproc
953         push    %rbx
954 .cfi_push       %rbx
955         push    %rbp
956 .cfi_push       %rbp
957         push    %r12
958 .cfi_push       %r12
959         push    %r13
960 .cfi_push       %r13
961         push    %r14
962 .cfi_push       %r14
963         push    %r15
964 .cfi_push       %r15
965
966         subq    \$`128+24+($win64?0xb0:0)`, %rsp
967 .cfi_adjust_cfa_offset  `128+24+($win64?0xb0:0)`
968 ___
969 $code.=<<___    if ($win64);
970         movaps  %xmm6,0xa0(%rsp)
971         movaps  %xmm7,0xb0(%rsp)
972         movaps  %xmm8,0xc0(%rsp)
973         movaps  %xmm9,0xd0(%rsp)
974         movaps  %xmm10,0xe0(%rsp)
975         movaps  %xmm11,0xf0(%rsp)
976         movaps  %xmm12,0x100(%rsp)
977         movaps  %xmm13,0x110(%rsp)
978         movaps  %xmm14,0x120(%rsp)
979         movaps  %xmm15,0x130(%rsp)
980 ___
981 $code.=<<___;
982 .Lmul_gather4_body:
983         movd    $pwr,%xmm8
984         movdqa  .Linc+16(%rip),%xmm1    # 00000002000000020000000200000002
985         movdqa  .Linc(%rip),%xmm0       # 00000001000000010000000000000000
986
987         pshufd  \$0,%xmm8,%xmm8         # broadcast $power
988         movdqa  %xmm1,%xmm7
989         movdqa  %xmm1,%xmm2
990 ___
991 ########################################################################
992 # calculate mask by comparing 0..15 to $power
993 #
994 for($i=0;$i<4;$i++) {
995 $code.=<<___;
996         paddd   %xmm`$i`,%xmm`$i+1`
997         pcmpeqd %xmm8,%xmm`$i`
998         movdqa  %xmm7,%xmm`$i+3`
999 ___
1000 }
1001 for(;$i<7;$i++) {
1002 $code.=<<___;
1003         paddd   %xmm`$i`,%xmm`$i+1`
1004         pcmpeqd %xmm8,%xmm`$i`
1005 ___
1006 }
1007 $code.=<<___;
1008         pcmpeqd %xmm8,%xmm7
1009
1010         movdqa  16*0($bp),%xmm8
1011         movdqa  16*1($bp),%xmm9
1012         movdqa  16*2($bp),%xmm10
1013         movdqa  16*3($bp),%xmm11
1014         pand    %xmm0,%xmm8
1015         movdqa  16*4($bp),%xmm12
1016         pand    %xmm1,%xmm9
1017         movdqa  16*5($bp),%xmm13
1018         pand    %xmm2,%xmm10
1019         movdqa  16*6($bp),%xmm14
1020         pand    %xmm3,%xmm11
1021         movdqa  16*7($bp),%xmm15
1022         leaq    128($bp), %rbp
1023         pand    %xmm4,%xmm12
1024         pand    %xmm5,%xmm13
1025         pand    %xmm6,%xmm14
1026         pand    %xmm7,%xmm15
1027         por     %xmm10,%xmm8
1028         por     %xmm11,%xmm9
1029         por     %xmm12,%xmm8
1030         por     %xmm13,%xmm9
1031         por     %xmm14,%xmm8
1032         por     %xmm15,%xmm9
1033
1034         por     %xmm9,%xmm8
1035         pshufd  \$0x4e,%xmm8,%xmm9
1036         por     %xmm9,%xmm8
1037 ___
1038 $code.=<<___ if ($addx);
1039         movl    \$0x80100,%r11d
1040         andl    OPENSSL_ia32cap_P+8(%rip),%r11d
1041         cmpl    \$0x80100,%r11d         # check for MULX and ADO/CX
1042         je      .Lmulx_gather
1043 ___
1044 $code.=<<___;
1045         movq    %xmm8,%rbx
1046
1047         movq    $n0, 128(%rsp)          # off-load arguments
1048         movq    $out, 128+8(%rsp)
1049         movq    $mod, 128+16(%rsp)
1050
1051         movq    ($ap), %rax
1052          movq   8($ap), %rcx
1053         mulq    %rbx                    # 0 iteration
1054         movq    %rax, (%rsp)
1055         movq    %rcx, %rax
1056         movq    %rdx, %r8
1057
1058         mulq    %rbx
1059         addq    %rax, %r8
1060         movq    16($ap), %rax
1061         movq    %rdx, %r9
1062         adcq    \$0, %r9
1063
1064         mulq    %rbx
1065         addq    %rax, %r9
1066         movq    24($ap), %rax
1067         movq    %rdx, %r10
1068         adcq    \$0, %r10
1069
1070         mulq    %rbx
1071         addq    %rax, %r10
1072         movq    32($ap), %rax
1073         movq    %rdx, %r11
1074         adcq    \$0, %r11
1075
1076         mulq    %rbx
1077         addq    %rax, %r11
1078         movq    40($ap), %rax
1079         movq    %rdx, %r12
1080         adcq    \$0, %r12
1081
1082         mulq    %rbx
1083         addq    %rax, %r12
1084         movq    48($ap), %rax
1085         movq    %rdx, %r13
1086         adcq    \$0, %r13
1087
1088         mulq    %rbx
1089         addq    %rax, %r13
1090         movq    56($ap), %rax
1091         movq    %rdx, %r14
1092         adcq    \$0, %r14
1093
1094         mulq    %rbx
1095         addq    %rax, %r14
1096          movq   ($ap), %rax
1097         movq    %rdx, %r15
1098         adcq    \$0, %r15
1099
1100         leaq    8(%rsp), %rdi
1101         movl    \$7, %ecx
1102         jmp     .Loop_mul_gather
1103
1104 .align  32
1105 .Loop_mul_gather:
1106         movdqa  16*0(%rbp),%xmm8
1107         movdqa  16*1(%rbp),%xmm9
1108         movdqa  16*2(%rbp),%xmm10
1109         movdqa  16*3(%rbp),%xmm11
1110         pand    %xmm0,%xmm8
1111         movdqa  16*4(%rbp),%xmm12
1112         pand    %xmm1,%xmm9
1113         movdqa  16*5(%rbp),%xmm13
1114         pand    %xmm2,%xmm10
1115         movdqa  16*6(%rbp),%xmm14
1116         pand    %xmm3,%xmm11
1117         movdqa  16*7(%rbp),%xmm15
1118         leaq    128(%rbp), %rbp
1119         pand    %xmm4,%xmm12
1120         pand    %xmm5,%xmm13
1121         pand    %xmm6,%xmm14
1122         pand    %xmm7,%xmm15
1123         por     %xmm10,%xmm8
1124         por     %xmm11,%xmm9
1125         por     %xmm12,%xmm8
1126         por     %xmm13,%xmm9
1127         por     %xmm14,%xmm8
1128         por     %xmm15,%xmm9
1129
1130         por     %xmm9,%xmm8
1131         pshufd  \$0x4e,%xmm8,%xmm9
1132         por     %xmm9,%xmm8
1133         movq    %xmm8,%rbx
1134
1135         mulq    %rbx
1136         addq    %rax, %r8
1137         movq    8($ap), %rax
1138         movq    %r8, (%rdi)
1139         movq    %rdx, %r8
1140         adcq    \$0, %r8
1141
1142         mulq    %rbx
1143         addq    %rax, %r9
1144         movq    16($ap), %rax
1145         adcq    \$0, %rdx
1146         addq    %r9, %r8
1147         movq    %rdx, %r9
1148         adcq    \$0, %r9
1149
1150         mulq    %rbx
1151         addq    %rax, %r10
1152         movq    24($ap), %rax
1153         adcq    \$0, %rdx
1154         addq    %r10, %r9
1155         movq    %rdx, %r10
1156         adcq    \$0, %r10
1157
1158         mulq    %rbx
1159         addq    %rax, %r11
1160         movq    32($ap), %rax
1161         adcq    \$0, %rdx
1162         addq    %r11, %r10
1163         movq    %rdx, %r11
1164         adcq    \$0, %r11
1165
1166         mulq    %rbx
1167         addq    %rax, %r12
1168         movq    40($ap), %rax
1169         adcq    \$0, %rdx
1170         addq    %r12, %r11
1171         movq    %rdx, %r12
1172         adcq    \$0, %r12
1173
1174         mulq    %rbx
1175         addq    %rax, %r13
1176         movq    48($ap), %rax
1177         adcq    \$0, %rdx
1178         addq    %r13, %r12
1179         movq    %rdx, %r13
1180         adcq    \$0, %r13
1181
1182         mulq    %rbx
1183         addq    %rax, %r14
1184         movq    56($ap), %rax
1185         adcq    \$0, %rdx
1186         addq    %r14, %r13
1187         movq    %rdx, %r14
1188         adcq    \$0, %r14
1189
1190         mulq    %rbx
1191         addq    %rax, %r15
1192          movq   ($ap), %rax
1193         adcq    \$0, %rdx
1194         addq    %r15, %r14
1195         movq    %rdx, %r15
1196         adcq    \$0, %r15
1197
1198         leaq    8(%rdi), %rdi
1199
1200         decl    %ecx
1201         jnz     .Loop_mul_gather
1202
1203         movq    %r8, (%rdi)
1204         movq    %r9, 8(%rdi)
1205         movq    %r10, 16(%rdi)
1206         movq    %r11, 24(%rdi)
1207         movq    %r12, 32(%rdi)
1208         movq    %r13, 40(%rdi)
1209         movq    %r14, 48(%rdi)
1210         movq    %r15, 56(%rdi)
1211
1212         movq    128+8(%rsp), $out
1213         movq    128+16(%rsp), %rbp
1214
1215         movq    (%rsp), %r8
1216         movq    8(%rsp), %r9
1217         movq    16(%rsp), %r10
1218         movq    24(%rsp), %r11
1219         movq    32(%rsp), %r12
1220         movq    40(%rsp), %r13
1221         movq    48(%rsp), %r14
1222         movq    56(%rsp), %r15
1223
1224         call    __rsaz_512_reduce
1225 ___
1226 $code.=<<___ if ($addx);
1227         jmp     .Lmul_gather_tail
1228
1229 .align  32
1230 .Lmulx_gather:
1231         movq    %xmm8,%rdx
1232
1233         mov     $n0, 128(%rsp)          # off-load arguments
1234         mov     $out, 128+8(%rsp)
1235         mov     $mod, 128+16(%rsp)
1236
1237         mulx    ($ap), %rbx, %r8        # 0 iteration
1238         mov     %rbx, (%rsp)
1239         xor     %edi, %edi              # cf=0, of=0
1240
1241         mulx    8($ap), %rax, %r9
1242
1243         mulx    16($ap), %rbx, %r10
1244         adcx    %rax, %r8
1245
1246         mulx    24($ap), %rax, %r11
1247         adcx    %rbx, %r9
1248
1249         mulx    32($ap), %rbx, %r12
1250         adcx    %rax, %r10
1251
1252         mulx    40($ap), %rax, %r13
1253         adcx    %rbx, %r11
1254
1255         mulx    48($ap), %rbx, %r14
1256         adcx    %rax, %r12
1257
1258         mulx    56($ap), %rax, %r15
1259         adcx    %rbx, %r13
1260         adcx    %rax, %r14
1261         .byte   0x67
1262         mov     %r8, %rbx
1263         adcx    %rdi, %r15              # %rdi is 0
1264
1265         mov     \$-7, %rcx
1266         jmp     .Loop_mulx_gather
1267
1268 .align  32
1269 .Loop_mulx_gather:
1270         movdqa  16*0(%rbp),%xmm8
1271         movdqa  16*1(%rbp),%xmm9
1272         movdqa  16*2(%rbp),%xmm10
1273         movdqa  16*3(%rbp),%xmm11
1274         pand    %xmm0,%xmm8
1275         movdqa  16*4(%rbp),%xmm12
1276         pand    %xmm1,%xmm9
1277         movdqa  16*5(%rbp),%xmm13
1278         pand    %xmm2,%xmm10
1279         movdqa  16*6(%rbp),%xmm14
1280         pand    %xmm3,%xmm11
1281         movdqa  16*7(%rbp),%xmm15
1282         leaq    128(%rbp), %rbp
1283         pand    %xmm4,%xmm12
1284         pand    %xmm5,%xmm13
1285         pand    %xmm6,%xmm14
1286         pand    %xmm7,%xmm15
1287         por     %xmm10,%xmm8
1288         por     %xmm11,%xmm9
1289         por     %xmm12,%xmm8
1290         por     %xmm13,%xmm9
1291         por     %xmm14,%xmm8
1292         por     %xmm15,%xmm9
1293
1294         por     %xmm9,%xmm8
1295         pshufd  \$0x4e,%xmm8,%xmm9
1296         por     %xmm9,%xmm8
1297         movq    %xmm8,%rdx
1298
1299         .byte   0xc4,0x62,0xfb,0xf6,0x86,0x00,0x00,0x00,0x00    # mulx  ($ap), %rax, %r8
1300         adcx    %rax, %rbx
1301         adox    %r9, %r8
1302
1303         mulx    8($ap), %rax, %r9
1304         adcx    %rax, %r8
1305         adox    %r10, %r9
1306
1307         mulx    16($ap), %rax, %r10
1308         adcx    %rax, %r9
1309         adox    %r11, %r10
1310
1311         .byte   0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00    # mulx  24($ap), %rax, %r11
1312         adcx    %rax, %r10
1313         adox    %r12, %r11
1314
1315         mulx    32($ap), %rax, %r12
1316         adcx    %rax, %r11
1317         adox    %r13, %r12
1318
1319         mulx    40($ap), %rax, %r13
1320         adcx    %rax, %r12
1321         adox    %r14, %r13
1322
1323         .byte   0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00    # mulx  48($ap), %rax, %r14
1324         adcx    %rax, %r13
1325         .byte   0x67
1326         adox    %r15, %r14
1327
1328         mulx    56($ap), %rax, %r15
1329          mov    %rbx, 64(%rsp,%rcx,8)
1330         adcx    %rax, %r14
1331         adox    %rdi, %r15
1332         mov     %r8, %rbx
1333         adcx    %rdi, %r15              # cf=0
1334
1335         inc     %rcx                    # of=0
1336         jnz     .Loop_mulx_gather
1337
1338         mov     %r8, 64(%rsp)
1339         mov     %r9, 64+8(%rsp)
1340         mov     %r10, 64+16(%rsp)
1341         mov     %r11, 64+24(%rsp)
1342         mov     %r12, 64+32(%rsp)
1343         mov     %r13, 64+40(%rsp)
1344         mov     %r14, 64+48(%rsp)
1345         mov     %r15, 64+56(%rsp)
1346
1347         mov     128(%rsp), %rdx         # pull arguments
1348         mov     128+8(%rsp), $out
1349         mov     128+16(%rsp), %rbp
1350
1351         mov     (%rsp), %r8
1352         mov     8(%rsp), %r9
1353         mov     16(%rsp), %r10
1354         mov     24(%rsp), %r11
1355         mov     32(%rsp), %r12
1356         mov     40(%rsp), %r13
1357         mov     48(%rsp), %r14
1358         mov     56(%rsp), %r15
1359
1360         call    __rsaz_512_reducex
1361
1362 .Lmul_gather_tail:
1363 ___
1364 $code.=<<___;
1365         addq    64(%rsp), %r8
1366         adcq    72(%rsp), %r9
1367         adcq    80(%rsp), %r10
1368         adcq    88(%rsp), %r11
1369         adcq    96(%rsp), %r12
1370         adcq    104(%rsp), %r13
1371         adcq    112(%rsp), %r14
1372         adcq    120(%rsp), %r15
1373         sbbq    %rcx, %rcx
1374
1375         call    __rsaz_512_subtract
1376
1377         leaq    128+24+48(%rsp), %rax
1378 ___
1379 $code.=<<___    if ($win64);
1380         movaps  0xa0-0xc8(%rax),%xmm6
1381         movaps  0xb0-0xc8(%rax),%xmm7
1382         movaps  0xc0-0xc8(%rax),%xmm8
1383         movaps  0xd0-0xc8(%rax),%xmm9
1384         movaps  0xe0-0xc8(%rax),%xmm10
1385         movaps  0xf0-0xc8(%rax),%xmm11
1386         movaps  0x100-0xc8(%rax),%xmm12
1387         movaps  0x110-0xc8(%rax),%xmm13
1388         movaps  0x120-0xc8(%rax),%xmm14
1389         movaps  0x130-0xc8(%rax),%xmm15
1390         lea     0xb0(%rax),%rax
1391 ___
1392 $code.=<<___;
1393 .cfi_def_cfa    %rax,8
1394         movq    -48(%rax), %r15
1395 .cfi_restore    %r15
1396         movq    -40(%rax), %r14
1397 .cfi_restore    %r14
1398         movq    -32(%rax), %r13
1399 .cfi_restore    %r13
1400         movq    -24(%rax), %r12
1401 .cfi_restore    %r12
1402         movq    -16(%rax), %rbp
1403 .cfi_restore    %rbp
1404         movq    -8(%rax), %rbx
1405 .cfi_restore    %rbx
1406         leaq    (%rax), %rsp
1407 .cfi_def_cfa_register   %rsp
1408 .Lmul_gather4_epilogue:
1409         ret
1410 .cfi_endproc
1411 .size   rsaz_512_mul_gather4,.-rsaz_512_mul_gather4
1412 ___
1413 }
1414 {
1415 my ($out,$ap,$mod,$n0,$tbl,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
1416 $code.=<<___;
1417 .globl  rsaz_512_mul_scatter4
1418 .type   rsaz_512_mul_scatter4,\@function,6
1419 .align  32
1420 rsaz_512_mul_scatter4:
1421 .cfi_startproc
1422         push    %rbx
1423 .cfi_push       %rbx
1424         push    %rbp
1425 .cfi_push       %rbp
1426         push    %r12
1427 .cfi_push       %r12
1428         push    %r13
1429 .cfi_push       %r13
1430         push    %r14
1431 .cfi_push       %r14
1432         push    %r15
1433 .cfi_push       %r15
1434
1435         mov     $pwr, $pwr
1436         subq    \$128+24, %rsp
1437 .cfi_adjust_cfa_offset  128+24
1438 .Lmul_scatter4_body:
1439         leaq    ($tbl,$pwr,8), $tbl
1440         movq    $out, %xmm0             # off-load arguments
1441         movq    $mod, %xmm1
1442         movq    $tbl, %xmm2
1443         movq    $n0, 128(%rsp)
1444
1445         movq    $out, %rbp
1446 ___
1447 $code.=<<___ if ($addx);
1448         movl    \$0x80100,%r11d
1449         andl    OPENSSL_ia32cap_P+8(%rip),%r11d
1450         cmpl    \$0x80100,%r11d         # check for MULX and ADO/CX
1451         je      .Lmulx_scatter
1452 ___
1453 $code.=<<___;
1454         movq    ($out),%rbx             # pass b[0]
1455         call    __rsaz_512_mul
1456
1457         movq    %xmm0, $out
1458         movq    %xmm1, %rbp
1459
1460         movq    (%rsp), %r8
1461         movq    8(%rsp), %r9
1462         movq    16(%rsp), %r10
1463         movq    24(%rsp), %r11
1464         movq    32(%rsp), %r12
1465         movq    40(%rsp), %r13
1466         movq    48(%rsp), %r14
1467         movq    56(%rsp), %r15
1468
1469         call    __rsaz_512_reduce
1470 ___
1471 $code.=<<___ if ($addx);
1472         jmp     .Lmul_scatter_tail
1473
1474 .align  32
1475 .Lmulx_scatter:
1476         movq    ($out), %rdx            # pass b[0]
1477         call    __rsaz_512_mulx
1478
1479         movq    %xmm0, $out
1480         movq    %xmm1, %rbp
1481
1482         movq    128(%rsp), %rdx         # pull $n0
1483         movq    (%rsp), %r8
1484         movq    8(%rsp), %r9
1485         movq    16(%rsp), %r10
1486         movq    24(%rsp), %r11
1487         movq    32(%rsp), %r12
1488         movq    40(%rsp), %r13
1489         movq    48(%rsp), %r14
1490         movq    56(%rsp), %r15
1491
1492         call    __rsaz_512_reducex
1493
1494 .Lmul_scatter_tail:
1495 ___
1496 $code.=<<___;
1497         addq    64(%rsp), %r8
1498         adcq    72(%rsp), %r9
1499         adcq    80(%rsp), %r10
1500         adcq    88(%rsp), %r11
1501         adcq    96(%rsp), %r12
1502         adcq    104(%rsp), %r13
1503         adcq    112(%rsp), %r14
1504         adcq    120(%rsp), %r15
1505         movq    %xmm2, $inp
1506         sbbq    %rcx, %rcx
1507
1508         call    __rsaz_512_subtract
1509
1510         movq    %r8, 128*0($inp)        # scatter
1511         movq    %r9, 128*1($inp)
1512         movq    %r10, 128*2($inp)
1513         movq    %r11, 128*3($inp)
1514         movq    %r12, 128*4($inp)
1515         movq    %r13, 128*5($inp)
1516         movq    %r14, 128*6($inp)
1517         movq    %r15, 128*7($inp)
1518
1519         leaq    128+24+48(%rsp), %rax
1520 .cfi_def_cfa    %rax,8
1521         movq    -48(%rax), %r15
1522 .cfi_restore    %r15
1523         movq    -40(%rax), %r14
1524 .cfi_restore    %r14
1525         movq    -32(%rax), %r13
1526 .cfi_restore    %r13
1527         movq    -24(%rax), %r12
1528 .cfi_restore    %r12
1529         movq    -16(%rax), %rbp
1530 .cfi_restore    %rbp
1531         movq    -8(%rax), %rbx
1532 .cfi_restore    %rbx
1533         leaq    (%rax), %rsp
1534 .cfi_def_cfa_register   %rsp
1535 .Lmul_scatter4_epilogue:
1536         ret
1537 .cfi_endproc
1538 .size   rsaz_512_mul_scatter4,.-rsaz_512_mul_scatter4
1539 ___
1540 }
1541 {
1542 my ($out,$inp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx");
1543 $code.=<<___;
1544 .globl  rsaz_512_mul_by_one
1545 .type   rsaz_512_mul_by_one,\@function,4
1546 .align  32
1547 rsaz_512_mul_by_one:
1548 .cfi_startproc
1549         push    %rbx
1550 .cfi_push       %rbx
1551         push    %rbp
1552 .cfi_push       %rbp
1553         push    %r12
1554 .cfi_push       %r12
1555         push    %r13
1556 .cfi_push       %r13
1557         push    %r14
1558 .cfi_push       %r14
1559         push    %r15
1560 .cfi_push       %r15
1561
1562         subq    \$128+24, %rsp
1563 .cfi_adjust_cfa_offset  128+24
1564 .Lmul_by_one_body:
1565 ___
1566 $code.=<<___ if ($addx);
1567         movl    OPENSSL_ia32cap_P+8(%rip),%eax
1568 ___
1569 $code.=<<___;
1570         movq    $mod, %rbp      # reassign argument
1571         movq    $n0, 128(%rsp)
1572
1573         movq    ($inp), %r8
1574         pxor    %xmm0, %xmm0
1575         movq    8($inp), %r9
1576         movq    16($inp), %r10
1577         movq    24($inp), %r11
1578         movq    32($inp), %r12
1579         movq    40($inp), %r13
1580         movq    48($inp), %r14
1581         movq    56($inp), %r15
1582
1583         movdqa  %xmm0, (%rsp)
1584         movdqa  %xmm0, 16(%rsp)
1585         movdqa  %xmm0, 32(%rsp)
1586         movdqa  %xmm0, 48(%rsp)
1587         movdqa  %xmm0, 64(%rsp)
1588         movdqa  %xmm0, 80(%rsp)
1589         movdqa  %xmm0, 96(%rsp)
1590 ___
1591 $code.=<<___ if ($addx);
1592         andl    \$0x80100,%eax
1593         cmpl    \$0x80100,%eax          # check for MULX and ADO/CX
1594         je      .Lby_one_callx
1595 ___
1596 $code.=<<___;
1597         call    __rsaz_512_reduce
1598 ___
1599 $code.=<<___ if ($addx);
1600         jmp     .Lby_one_tail
1601 .align  32
1602 .Lby_one_callx:
1603         movq    128(%rsp), %rdx         # pull $n0
1604         call    __rsaz_512_reducex
1605 .Lby_one_tail:
1606 ___
1607 $code.=<<___;
1608         movq    %r8, ($out)
1609         movq    %r9, 8($out)
1610         movq    %r10, 16($out)
1611         movq    %r11, 24($out)
1612         movq    %r12, 32($out)
1613         movq    %r13, 40($out)
1614         movq    %r14, 48($out)
1615         movq    %r15, 56($out)
1616
1617         leaq    128+24+48(%rsp), %rax
1618 .cfi_def_cfa    %rax,8
1619         movq    -48(%rax), %r15
1620 .cfi_restore    %r15
1621         movq    -40(%rax), %r14
1622 .cfi_restore    %r14
1623         movq    -32(%rax), %r13
1624 .cfi_restore    %r13
1625         movq    -24(%rax), %r12
1626 .cfi_restore    %r12
1627         movq    -16(%rax), %rbp
1628 .cfi_restore    %rbp
1629         movq    -8(%rax), %rbx
1630 .cfi_restore    %rbx
1631         leaq    (%rax), %rsp
1632 .cfi_def_cfa_register   %rsp
1633 .Lmul_by_one_epilogue:
1634         ret
1635 .cfi_endproc
1636 .size   rsaz_512_mul_by_one,.-rsaz_512_mul_by_one
1637 ___
1638 }
1639 {       # __rsaz_512_reduce
1640         #
1641         # input:        %r8-%r15, %rbp - mod, 128(%rsp) - n0
1642         # output:       %r8-%r15
1643         # clobbers:     everything except %rbp and %rdi
1644 $code.=<<___;
1645 .type   __rsaz_512_reduce,\@abi-omnipotent
1646 .align  32
1647 __rsaz_512_reduce:
1648         movq    %r8, %rbx
1649         imulq   128+8(%rsp), %rbx
1650         movq    0(%rbp), %rax
1651         movl    \$8, %ecx
1652         jmp     .Lreduction_loop
1653
1654 .align  32
1655 .Lreduction_loop:
1656         mulq    %rbx
1657         movq    8(%rbp), %rax
1658         negq    %r8
1659         movq    %rdx, %r8
1660         adcq    \$0, %r8
1661
1662         mulq    %rbx
1663         addq    %rax, %r9
1664         movq    16(%rbp), %rax
1665         adcq    \$0, %rdx
1666         addq    %r9, %r8
1667         movq    %rdx, %r9
1668         adcq    \$0, %r9
1669
1670         mulq    %rbx
1671         addq    %rax, %r10
1672         movq    24(%rbp), %rax
1673         adcq    \$0, %rdx
1674         addq    %r10, %r9
1675         movq    %rdx, %r10
1676         adcq    \$0, %r10
1677
1678         mulq    %rbx
1679         addq    %rax, %r11
1680         movq    32(%rbp), %rax
1681         adcq    \$0, %rdx
1682         addq    %r11, %r10
1683          movq   128+8(%rsp), %rsi
1684         #movq   %rdx, %r11
1685         #adcq   \$0, %r11
1686         adcq    \$0, %rdx
1687         movq    %rdx, %r11
1688
1689         mulq    %rbx
1690         addq    %rax, %r12
1691         movq    40(%rbp), %rax
1692         adcq    \$0, %rdx
1693          imulq  %r8, %rsi
1694         addq    %r12, %r11
1695         movq    %rdx, %r12
1696         adcq    \$0, %r12
1697
1698         mulq    %rbx
1699         addq    %rax, %r13
1700         movq    48(%rbp), %rax
1701         adcq    \$0, %rdx
1702         addq    %r13, %r12
1703         movq    %rdx, %r13
1704         adcq    \$0, %r13
1705
1706         mulq    %rbx
1707         addq    %rax, %r14
1708         movq    56(%rbp), %rax
1709         adcq    \$0, %rdx
1710         addq    %r14, %r13
1711         movq    %rdx, %r14
1712         adcq    \$0, %r14
1713
1714         mulq    %rbx
1715          movq   %rsi, %rbx
1716         addq    %rax, %r15
1717          movq   0(%rbp), %rax
1718         adcq    \$0, %rdx
1719         addq    %r15, %r14
1720         movq    %rdx, %r15
1721         adcq    \$0, %r15
1722
1723         decl    %ecx
1724         jne     .Lreduction_loop
1725
1726         ret
1727 .size   __rsaz_512_reduce,.-__rsaz_512_reduce
1728 ___
1729 }
1730 if ($addx) {
1731         # __rsaz_512_reducex
1732         #
1733         # input:        %r8-%r15, %rbp - mod, 128(%rsp) - n0
1734         # output:       %r8-%r15
1735         # clobbers:     everything except %rbp and %rdi
1736 $code.=<<___;
1737 .type   __rsaz_512_reducex,\@abi-omnipotent
1738 .align  32
1739 __rsaz_512_reducex:
1740         #movq   128+8(%rsp), %rdx               # pull $n0
1741         imulq   %r8, %rdx
1742         xorq    %rsi, %rsi                      # cf=0,of=0
1743         movl    \$8, %ecx
1744         jmp     .Lreduction_loopx
1745
1746 .align  32
1747 .Lreduction_loopx:
1748         mov     %r8, %rbx
1749         mulx    0(%rbp), %rax, %r8
1750         adcx    %rbx, %rax
1751         adox    %r9, %r8
1752
1753         mulx    8(%rbp), %rax, %r9
1754         adcx    %rax, %r8
1755         adox    %r10, %r9
1756
1757         mulx    16(%rbp), %rbx, %r10
1758         adcx    %rbx, %r9
1759         adox    %r11, %r10
1760
1761         mulx    24(%rbp), %rbx, %r11
1762         adcx    %rbx, %r10
1763         adox    %r12, %r11
1764
1765         .byte   0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00    # mulx  32(%rbp), %rbx, %r12
1766          mov    %rdx, %rax
1767          mov    %r8, %rdx
1768         adcx    %rbx, %r11
1769         adox    %r13, %r12
1770
1771          mulx   128+8(%rsp), %rbx, %rdx
1772          mov    %rax, %rdx
1773
1774         mulx    40(%rbp), %rax, %r13
1775         adcx    %rax, %r12
1776         adox    %r14, %r13
1777
1778         .byte   0xc4,0x62,0xfb,0xf6,0xb5,0x30,0x00,0x00,0x00    # mulx  48(%rbp), %rax, %r14
1779         adcx    %rax, %r13
1780         adox    %r15, %r14
1781
1782         mulx    56(%rbp), %rax, %r15
1783          mov    %rbx, %rdx
1784         adcx    %rax, %r14
1785         adox    %rsi, %r15                      # %rsi is 0
1786         adcx    %rsi, %r15                      # cf=0
1787
1788         decl    %ecx                            # of=0
1789         jne     .Lreduction_loopx
1790
1791         ret
1792 .size   __rsaz_512_reducex,.-__rsaz_512_reducex
1793 ___
1794 }
1795 {       # __rsaz_512_subtract
1796         # input: %r8-%r15, %rdi - $out, %rbp - $mod, %rcx - mask
1797         # output:
1798         # clobbers: everything but %rdi, %rsi and %rbp
1799 $code.=<<___;
1800 .type   __rsaz_512_subtract,\@abi-omnipotent
1801 .align  32
1802 __rsaz_512_subtract:
1803         movq    %r8, ($out)
1804         movq    %r9, 8($out)
1805         movq    %r10, 16($out)
1806         movq    %r11, 24($out)
1807         movq    %r12, 32($out)
1808         movq    %r13, 40($out)
1809         movq    %r14, 48($out)
1810         movq    %r15, 56($out)
1811
1812         movq    0($mod), %r8
1813         movq    8($mod), %r9
1814         negq    %r8
1815         notq    %r9
1816         andq    %rcx, %r8
1817         movq    16($mod), %r10
1818         andq    %rcx, %r9
1819         notq    %r10
1820         movq    24($mod), %r11
1821         andq    %rcx, %r10
1822         notq    %r11
1823         movq    32($mod), %r12
1824         andq    %rcx, %r11
1825         notq    %r12
1826         movq    40($mod), %r13
1827         andq    %rcx, %r12
1828         notq    %r13
1829         movq    48($mod), %r14
1830         andq    %rcx, %r13
1831         notq    %r14
1832         movq    56($mod), %r15
1833         andq    %rcx, %r14
1834         notq    %r15
1835         andq    %rcx, %r15
1836
1837         addq    ($out), %r8
1838         adcq    8($out), %r9
1839         adcq    16($out), %r10
1840         adcq    24($out), %r11
1841         adcq    32($out), %r12
1842         adcq    40($out), %r13
1843         adcq    48($out), %r14
1844         adcq    56($out), %r15
1845
1846         movq    %r8, ($out)
1847         movq    %r9, 8($out)
1848         movq    %r10, 16($out)
1849         movq    %r11, 24($out)
1850         movq    %r12, 32($out)
1851         movq    %r13, 40($out)
1852         movq    %r14, 48($out)
1853         movq    %r15, 56($out)
1854
1855         ret
1856 .size   __rsaz_512_subtract,.-__rsaz_512_subtract
1857 ___
1858 }
1859 {       # __rsaz_512_mul
1860         #
1861         # input: %rsi - ap, %rbp - bp
1862         # output:
1863         # clobbers: everything
1864 my ($ap,$bp) = ("%rsi","%rbp");
1865 $code.=<<___;
1866 .type   __rsaz_512_mul,\@abi-omnipotent
1867 .align  32
1868 __rsaz_512_mul:
1869         leaq    8(%rsp), %rdi
1870
1871         movq    ($ap), %rax
1872         mulq    %rbx
1873         movq    %rax, (%rdi)
1874         movq    8($ap), %rax
1875         movq    %rdx, %r8
1876
1877         mulq    %rbx
1878         addq    %rax, %r8
1879         movq    16($ap), %rax
1880         movq    %rdx, %r9
1881         adcq    \$0, %r9
1882
1883         mulq    %rbx
1884         addq    %rax, %r9
1885         movq    24($ap), %rax
1886         movq    %rdx, %r10
1887         adcq    \$0, %r10
1888
1889         mulq    %rbx
1890         addq    %rax, %r10
1891         movq    32($ap), %rax
1892         movq    %rdx, %r11
1893         adcq    \$0, %r11
1894
1895         mulq    %rbx
1896         addq    %rax, %r11
1897         movq    40($ap), %rax
1898         movq    %rdx, %r12
1899         adcq    \$0, %r12
1900
1901         mulq    %rbx
1902         addq    %rax, %r12
1903         movq    48($ap), %rax
1904         movq    %rdx, %r13
1905         adcq    \$0, %r13
1906
1907         mulq    %rbx
1908         addq    %rax, %r13
1909         movq    56($ap), %rax
1910         movq    %rdx, %r14
1911         adcq    \$0, %r14
1912
1913         mulq    %rbx
1914         addq    %rax, %r14
1915          movq   ($ap), %rax
1916         movq    %rdx, %r15
1917         adcq    \$0, %r15
1918
1919         leaq    8($bp), $bp
1920         leaq    8(%rdi), %rdi
1921
1922         movl    \$7, %ecx
1923         jmp     .Loop_mul
1924
1925 .align  32
1926 .Loop_mul:
1927         movq    ($bp), %rbx
1928         mulq    %rbx
1929         addq    %rax, %r8
1930         movq    8($ap), %rax
1931         movq    %r8, (%rdi)
1932         movq    %rdx, %r8
1933         adcq    \$0, %r8
1934
1935         mulq    %rbx
1936         addq    %rax, %r9
1937         movq    16($ap), %rax
1938         adcq    \$0, %rdx
1939         addq    %r9, %r8
1940         movq    %rdx, %r9
1941         adcq    \$0, %r9
1942
1943         mulq    %rbx
1944         addq    %rax, %r10
1945         movq    24($ap), %rax
1946         adcq    \$0, %rdx
1947         addq    %r10, %r9
1948         movq    %rdx, %r10
1949         adcq    \$0, %r10
1950
1951         mulq    %rbx
1952         addq    %rax, %r11
1953         movq    32($ap), %rax
1954         adcq    \$0, %rdx
1955         addq    %r11, %r10
1956         movq    %rdx, %r11
1957         adcq    \$0, %r11
1958
1959         mulq    %rbx
1960         addq    %rax, %r12
1961         movq    40($ap), %rax
1962         adcq    \$0, %rdx
1963         addq    %r12, %r11
1964         movq    %rdx, %r12
1965         adcq    \$0, %r12
1966
1967         mulq    %rbx
1968         addq    %rax, %r13
1969         movq    48($ap), %rax
1970         adcq    \$0, %rdx
1971         addq    %r13, %r12
1972         movq    %rdx, %r13
1973         adcq    \$0, %r13
1974
1975         mulq    %rbx
1976         addq    %rax, %r14
1977         movq    56($ap), %rax
1978         adcq    \$0, %rdx
1979         addq    %r14, %r13
1980         movq    %rdx, %r14
1981          leaq   8($bp), $bp
1982         adcq    \$0, %r14
1983
1984         mulq    %rbx
1985         addq    %rax, %r15
1986          movq   ($ap), %rax
1987         adcq    \$0, %rdx
1988         addq    %r15, %r14
1989         movq    %rdx, %r15
1990         adcq    \$0, %r15
1991
1992         leaq    8(%rdi), %rdi
1993
1994         decl    %ecx
1995         jnz     .Loop_mul
1996
1997         movq    %r8, (%rdi)
1998         movq    %r9, 8(%rdi)
1999         movq    %r10, 16(%rdi)
2000         movq    %r11, 24(%rdi)
2001         movq    %r12, 32(%rdi)
2002         movq    %r13, 40(%rdi)
2003         movq    %r14, 48(%rdi)
2004         movq    %r15, 56(%rdi)
2005
2006         ret
2007 .size   __rsaz_512_mul,.-__rsaz_512_mul
2008 ___
2009 }
2010 if ($addx) {
2011         # __rsaz_512_mulx
2012         #
2013         # input: %rsi - ap, %rbp - bp
2014         # output:
2015         # clobbers: everything
2016 my ($ap,$bp,$zero) = ("%rsi","%rbp","%rdi");
2017 $code.=<<___;
2018 .type   __rsaz_512_mulx,\@abi-omnipotent
2019 .align  32
2020 __rsaz_512_mulx:
2021         mulx    ($ap), %rbx, %r8        # initial %rdx preloaded by caller
2022         mov     \$-6, %rcx
2023
2024         mulx    8($ap), %rax, %r9
2025         movq    %rbx, 8(%rsp)
2026
2027         mulx    16($ap), %rbx, %r10
2028         adc     %rax, %r8
2029
2030         mulx    24($ap), %rax, %r11
2031         adc     %rbx, %r9
2032
2033         mulx    32($ap), %rbx, %r12
2034         adc     %rax, %r10
2035
2036         mulx    40($ap), %rax, %r13
2037         adc     %rbx, %r11
2038
2039         mulx    48($ap), %rbx, %r14
2040         adc     %rax, %r12
2041
2042         mulx    56($ap), %rax, %r15
2043          mov    8($bp), %rdx
2044         adc     %rbx, %r13
2045         adc     %rax, %r14
2046         adc     \$0, %r15
2047
2048         xor     $zero, $zero            # cf=0,of=0
2049         jmp     .Loop_mulx
2050
2051 .align  32
2052 .Loop_mulx:
2053         movq    %r8, %rbx
2054         mulx    ($ap), %rax, %r8
2055         adcx    %rax, %rbx
2056         adox    %r9, %r8
2057
2058         mulx    8($ap), %rax, %r9
2059         adcx    %rax, %r8
2060         adox    %r10, %r9
2061
2062         mulx    16($ap), %rax, %r10
2063         adcx    %rax, %r9
2064         adox    %r11, %r10
2065
2066         mulx    24($ap), %rax, %r11
2067         adcx    %rax, %r10
2068         adox    %r12, %r11
2069
2070         .byte   0x3e,0xc4,0x62,0xfb,0xf6,0xa6,0x20,0x00,0x00,0x00       # mulx  32($ap), %rax, %r12
2071         adcx    %rax, %r11
2072         adox    %r13, %r12
2073
2074         mulx    40($ap), %rax, %r13
2075         adcx    %rax, %r12
2076         adox    %r14, %r13
2077
2078         mulx    48($ap), %rax, %r14
2079         adcx    %rax, %r13
2080         adox    %r15, %r14
2081
2082         mulx    56($ap), %rax, %r15
2083          movq   64($bp,%rcx,8), %rdx
2084          movq   %rbx, 8+64-8(%rsp,%rcx,8)
2085         adcx    %rax, %r14
2086         adox    $zero, %r15
2087         adcx    $zero, %r15             # cf=0
2088
2089         inc     %rcx                    # of=0
2090         jnz     .Loop_mulx
2091
2092         movq    %r8, %rbx
2093         mulx    ($ap), %rax, %r8
2094         adcx    %rax, %rbx
2095         adox    %r9, %r8
2096
2097         .byte   0xc4,0x62,0xfb,0xf6,0x8e,0x08,0x00,0x00,0x00    # mulx  8($ap), %rax, %r9
2098         adcx    %rax, %r8
2099         adox    %r10, %r9
2100
2101         .byte   0xc4,0x62,0xfb,0xf6,0x96,0x10,0x00,0x00,0x00    # mulx  16($ap), %rax, %r10
2102         adcx    %rax, %r9
2103         adox    %r11, %r10
2104
2105         mulx    24($ap), %rax, %r11
2106         adcx    %rax, %r10
2107         adox    %r12, %r11
2108
2109         mulx    32($ap), %rax, %r12
2110         adcx    %rax, %r11
2111         adox    %r13, %r12
2112
2113         mulx    40($ap), %rax, %r13
2114         adcx    %rax, %r12
2115         adox    %r14, %r13
2116
2117         .byte   0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00    # mulx  48($ap), %rax, %r14
2118         adcx    %rax, %r13
2119         adox    %r15, %r14
2120
2121         .byte   0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00    # mulx  56($ap), %rax, %r15
2122         adcx    %rax, %r14
2123         adox    $zero, %r15
2124         adcx    $zero, %r15
2125
2126         mov     %rbx, 8+64-8(%rsp)
2127         mov     %r8, 8+64(%rsp)
2128         mov     %r9, 8+64+8(%rsp)
2129         mov     %r10, 8+64+16(%rsp)
2130         mov     %r11, 8+64+24(%rsp)
2131         mov     %r12, 8+64+32(%rsp)
2132         mov     %r13, 8+64+40(%rsp)
2133         mov     %r14, 8+64+48(%rsp)
2134         mov     %r15, 8+64+56(%rsp)
2135
2136         ret
2137 .size   __rsaz_512_mulx,.-__rsaz_512_mulx
2138 ___
2139 }
2140 {
2141 my ($out,$inp,$power)= $win64 ? ("%rcx","%rdx","%r8d") : ("%rdi","%rsi","%edx");
2142 $code.=<<___;
2143 .globl  rsaz_512_scatter4
2144 .type   rsaz_512_scatter4,\@abi-omnipotent
2145 .align  16
2146 rsaz_512_scatter4:
2147         leaq    ($out,$power,8), $out
2148         movl    \$8, %r9d
2149         jmp     .Loop_scatter
2150 .align  16
2151 .Loop_scatter:
2152         movq    ($inp), %rax
2153         leaq    8($inp), $inp
2154         movq    %rax, ($out)
2155         leaq    128($out), $out
2156         decl    %r9d
2157         jnz     .Loop_scatter
2158         ret
2159 .size   rsaz_512_scatter4,.-rsaz_512_scatter4
2160
2161 .globl  rsaz_512_gather4
2162 .type   rsaz_512_gather4,\@abi-omnipotent
2163 .align  16
2164 rsaz_512_gather4:
2165 ___
2166 $code.=<<___    if ($win64);
2167 .LSEH_begin_rsaz_512_gather4:
2168         .byte   0x48,0x81,0xec,0xa8,0x00,0x00,0x00      # sub    $0xa8,%rsp
2169         .byte   0x0f,0x29,0x34,0x24                     # movaps %xmm6,(%rsp)
2170         .byte   0x0f,0x29,0x7c,0x24,0x10                # movaps %xmm7,0x10(%rsp)
2171         .byte   0x44,0x0f,0x29,0x44,0x24,0x20           # movaps %xmm8,0x20(%rsp)
2172         .byte   0x44,0x0f,0x29,0x4c,0x24,0x30           # movaps %xmm9,0x30(%rsp)
2173         .byte   0x44,0x0f,0x29,0x54,0x24,0x40           # movaps %xmm10,0x40(%rsp)
2174         .byte   0x44,0x0f,0x29,0x5c,0x24,0x50           # movaps %xmm11,0x50(%rsp)
2175         .byte   0x44,0x0f,0x29,0x64,0x24,0x60           # movaps %xmm12,0x60(%rsp)
2176         .byte   0x44,0x0f,0x29,0x6c,0x24,0x70           # movaps %xmm13,0x70(%rsp)
2177         .byte   0x44,0x0f,0x29,0xb4,0x24,0x80,0,0,0     # movaps %xmm14,0x80(%rsp)
2178         .byte   0x44,0x0f,0x29,0xbc,0x24,0x90,0,0,0     # movaps %xmm15,0x90(%rsp)
2179 ___
2180 $code.=<<___;
2181         movd    $power,%xmm8
2182         movdqa  .Linc+16(%rip),%xmm1    # 00000002000000020000000200000002
2183         movdqa  .Linc(%rip),%xmm0       # 00000001000000010000000000000000
2184
2185         pshufd  \$0,%xmm8,%xmm8         # broadcast $power
2186         movdqa  %xmm1,%xmm7
2187         movdqa  %xmm1,%xmm2
2188 ___
2189 ########################################################################
2190 # calculate mask by comparing 0..15 to $power
2191 #
2192 for($i=0;$i<4;$i++) {
2193 $code.=<<___;
2194         paddd   %xmm`$i`,%xmm`$i+1`
2195         pcmpeqd %xmm8,%xmm`$i`
2196         movdqa  %xmm7,%xmm`$i+3`
2197 ___
2198 }
2199 for(;$i<7;$i++) {
2200 $code.=<<___;
2201         paddd   %xmm`$i`,%xmm`$i+1`
2202         pcmpeqd %xmm8,%xmm`$i`
2203 ___
2204 }
2205 $code.=<<___;
2206         pcmpeqd %xmm8,%xmm7
2207         movl    \$8, %r9d
2208         jmp     .Loop_gather
2209 .align  16
2210 .Loop_gather:
2211         movdqa  16*0($inp),%xmm8
2212         movdqa  16*1($inp),%xmm9
2213         movdqa  16*2($inp),%xmm10
2214         movdqa  16*3($inp),%xmm11
2215         pand    %xmm0,%xmm8
2216         movdqa  16*4($inp),%xmm12
2217         pand    %xmm1,%xmm9
2218         movdqa  16*5($inp),%xmm13
2219         pand    %xmm2,%xmm10
2220         movdqa  16*6($inp),%xmm14
2221         pand    %xmm3,%xmm11
2222         movdqa  16*7($inp),%xmm15
2223         leaq    128($inp), $inp
2224         pand    %xmm4,%xmm12
2225         pand    %xmm5,%xmm13
2226         pand    %xmm6,%xmm14
2227         pand    %xmm7,%xmm15
2228         por     %xmm10,%xmm8
2229         por     %xmm11,%xmm9
2230         por     %xmm12,%xmm8
2231         por     %xmm13,%xmm9
2232         por     %xmm14,%xmm8
2233         por     %xmm15,%xmm9
2234
2235         por     %xmm9,%xmm8
2236         pshufd  \$0x4e,%xmm8,%xmm9
2237         por     %xmm9,%xmm8
2238         movq    %xmm8,($out)
2239         leaq    8($out), $out
2240         decl    %r9d
2241         jnz     .Loop_gather
2242 ___
2243 $code.=<<___    if ($win64);
2244         movaps  0x00(%rsp),%xmm6
2245         movaps  0x10(%rsp),%xmm7
2246         movaps  0x20(%rsp),%xmm8
2247         movaps  0x30(%rsp),%xmm9
2248         movaps  0x40(%rsp),%xmm10
2249         movaps  0x50(%rsp),%xmm11
2250         movaps  0x60(%rsp),%xmm12
2251         movaps  0x70(%rsp),%xmm13
2252         movaps  0x80(%rsp),%xmm14
2253         movaps  0x90(%rsp),%xmm15
2254         add     \$0xa8,%rsp
2255 ___
2256 $code.=<<___;
2257         ret
2258 .LSEH_end_rsaz_512_gather4:
2259 .size   rsaz_512_gather4,.-rsaz_512_gather4
2260
2261 .align  64
2262 .Linc:
2263         .long   0,0, 1,1
2264         .long   2,2, 2,2
2265 ___
2266 }
2267
2268 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
2269 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
2270 if ($win64) {
2271 $rec="%rcx";
2272 $frame="%rdx";
2273 $context="%r8";
2274 $disp="%r9";
2275
2276 $code.=<<___;
2277 .extern __imp_RtlVirtualUnwind
2278 .type   se_handler,\@abi-omnipotent
2279 .align  16
2280 se_handler:
2281         push    %rsi
2282         push    %rdi
2283         push    %rbx
2284         push    %rbp
2285         push    %r12
2286         push    %r13
2287         push    %r14
2288         push    %r15
2289         pushfq
2290         sub     \$64,%rsp
2291
2292         mov     120($context),%rax      # pull context->Rax
2293         mov     248($context),%rbx      # pull context->Rip
2294
2295         mov     8($disp),%rsi           # disp->ImageBase
2296         mov     56($disp),%r11          # disp->HandlerData
2297
2298         mov     0(%r11),%r10d           # HandlerData[0]
2299         lea     (%rsi,%r10),%r10        # end of prologue label
2300         cmp     %r10,%rbx               # context->Rip<end of prologue label
2301         jb      .Lcommon_seh_tail
2302
2303         mov     152($context),%rax      # pull context->Rsp
2304
2305         mov     4(%r11),%r10d           # HandlerData[1]
2306         lea     (%rsi,%r10),%r10        # epilogue label
2307         cmp     %r10,%rbx               # context->Rip>=epilogue label
2308         jae     .Lcommon_seh_tail
2309
2310         lea     128+24+48(%rax),%rax
2311
2312         lea     .Lmul_gather4_epilogue(%rip),%rbx
2313         cmp     %r10,%rbx
2314         jne     .Lse_not_in_mul_gather4
2315
2316         lea     0xb0(%rax),%rax
2317
2318         lea     -48-0xa8(%rax),%rsi
2319         lea     512($context),%rdi
2320         mov     \$20,%ecx
2321         .long   0xa548f3fc              # cld; rep movsq
2322
2323 .Lse_not_in_mul_gather4:
2324         mov     -8(%rax),%rbx
2325         mov     -16(%rax),%rbp
2326         mov     -24(%rax),%r12
2327         mov     -32(%rax),%r13
2328         mov     -40(%rax),%r14
2329         mov     -48(%rax),%r15
2330         mov     %rbx,144($context)      # restore context->Rbx
2331         mov     %rbp,160($context)      # restore context->Rbp
2332         mov     %r12,216($context)      # restore context->R12
2333         mov     %r13,224($context)      # restore context->R13
2334         mov     %r14,232($context)      # restore context->R14
2335         mov     %r15,240($context)      # restore context->R15
2336
2337 .Lcommon_seh_tail:
2338         mov     8(%rax),%rdi
2339         mov     16(%rax),%rsi
2340         mov     %rax,152($context)      # restore context->Rsp
2341         mov     %rsi,168($context)      # restore context->Rsi
2342         mov     %rdi,176($context)      # restore context->Rdi
2343
2344         mov     40($disp),%rdi          # disp->ContextRecord
2345         mov     $context,%rsi           # context
2346         mov     \$154,%ecx              # sizeof(CONTEXT)
2347         .long   0xa548f3fc              # cld; rep movsq
2348
2349         mov     $disp,%rsi
2350         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
2351         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
2352         mov     0(%rsi),%r8             # arg3, disp->ControlPc
2353         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
2354         mov     40(%rsi),%r10           # disp->ContextRecord
2355         lea     56(%rsi),%r11           # &disp->HandlerData
2356         lea     24(%rsi),%r12           # &disp->EstablisherFrame
2357         mov     %r10,32(%rsp)           # arg5
2358         mov     %r11,40(%rsp)           # arg6
2359         mov     %r12,48(%rsp)           # arg7
2360         mov     %rcx,56(%rsp)           # arg8, (NULL)
2361         call    *__imp_RtlVirtualUnwind(%rip)
2362
2363         mov     \$1,%eax                # ExceptionContinueSearch
2364         add     \$64,%rsp
2365         popfq
2366         pop     %r15
2367         pop     %r14
2368         pop     %r13
2369         pop     %r12
2370         pop     %rbp
2371         pop     %rbx
2372         pop     %rdi
2373         pop     %rsi
2374         ret
2375 .size   se_handler,.-se_handler
2376
2377 .section        .pdata
2378 .align  4
2379         .rva    .LSEH_begin_rsaz_512_sqr
2380         .rva    .LSEH_end_rsaz_512_sqr
2381         .rva    .LSEH_info_rsaz_512_sqr
2382
2383         .rva    .LSEH_begin_rsaz_512_mul
2384         .rva    .LSEH_end_rsaz_512_mul
2385         .rva    .LSEH_info_rsaz_512_mul
2386
2387         .rva    .LSEH_begin_rsaz_512_mul_gather4
2388         .rva    .LSEH_end_rsaz_512_mul_gather4
2389         .rva    .LSEH_info_rsaz_512_mul_gather4
2390
2391         .rva    .LSEH_begin_rsaz_512_mul_scatter4
2392         .rva    .LSEH_end_rsaz_512_mul_scatter4
2393         .rva    .LSEH_info_rsaz_512_mul_scatter4
2394
2395         .rva    .LSEH_begin_rsaz_512_mul_by_one
2396         .rva    .LSEH_end_rsaz_512_mul_by_one
2397         .rva    .LSEH_info_rsaz_512_mul_by_one
2398
2399         .rva    .LSEH_begin_rsaz_512_gather4
2400         .rva    .LSEH_end_rsaz_512_gather4
2401         .rva    .LSEH_info_rsaz_512_gather4
2402
2403 .section        .xdata
2404 .align  8
2405 .LSEH_info_rsaz_512_sqr:
2406         .byte   9,0,0,0
2407         .rva    se_handler
2408         .rva    .Lsqr_body,.Lsqr_epilogue                       # HandlerData[]
2409 .LSEH_info_rsaz_512_mul:
2410         .byte   9,0,0,0
2411         .rva    se_handler
2412         .rva    .Lmul_body,.Lmul_epilogue                       # HandlerData[]
2413 .LSEH_info_rsaz_512_mul_gather4:
2414         .byte   9,0,0,0
2415         .rva    se_handler
2416         .rva    .Lmul_gather4_body,.Lmul_gather4_epilogue       # HandlerData[]
2417 .LSEH_info_rsaz_512_mul_scatter4:
2418         .byte   9,0,0,0
2419         .rva    se_handler
2420         .rva    .Lmul_scatter4_body,.Lmul_scatter4_epilogue     # HandlerData[]
2421 .LSEH_info_rsaz_512_mul_by_one:
2422         .byte   9,0,0,0
2423         .rva    se_handler
2424         .rva    .Lmul_by_one_body,.Lmul_by_one_epilogue         # HandlerData[]
2425 .LSEH_info_rsaz_512_gather4:
2426         .byte   0x01,0x46,0x16,0x00
2427         .byte   0x46,0xf8,0x09,0x00     # vmovaps 0x90(rsp),xmm15
2428         .byte   0x3d,0xe8,0x08,0x00     # vmovaps 0x80(rsp),xmm14
2429         .byte   0x34,0xd8,0x07,0x00     # vmovaps 0x70(rsp),xmm13
2430         .byte   0x2e,0xc8,0x06,0x00     # vmovaps 0x60(rsp),xmm12
2431         .byte   0x28,0xb8,0x05,0x00     # vmovaps 0x50(rsp),xmm11
2432         .byte   0x22,0xa8,0x04,0x00     # vmovaps 0x40(rsp),xmm10
2433         .byte   0x1c,0x98,0x03,0x00     # vmovaps 0x30(rsp),xmm9
2434         .byte   0x16,0x88,0x02,0x00     # vmovaps 0x20(rsp),xmm8
2435         .byte   0x10,0x78,0x01,0x00     # vmovaps 0x10(rsp),xmm7
2436         .byte   0x0b,0x68,0x00,0x00     # vmovaps 0x00(rsp),xmm6
2437         .byte   0x07,0x01,0x15,0x00     # sub     rsp,0xa8
2438 ___
2439 }
2440
2441 $code =~ s/\`([^\`]*)\`/eval $1/gem;
2442 print $code;
2443 close STDOUT;