Merge Intel copyright notice into standard
[openssl.git] / crypto / ec / asm / ecp_nistz256-x86_64.pl
1 #! /usr/bin/env perl
2 # Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
3 # Copyright (c) 2014, Intel Corporation. All Rights Reserved.
4 #
5 # Licensed under the OpenSSL license (the "License").  You may not use
6 # this file except in compliance with the License.  You can obtain a copy
7 # in the file LICENSE in the source distribution or at
8 # https://www.openssl.org/source/license.html
9 #
10 # Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1)
11 # (1) Intel Corporation, Israel Development Center, Haifa, Israel
12 # (2) University of Haifa, Israel
13 #
14 # Reference:
15 # S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with
16 #                          256 Bit Primes"
17
18 # Further optimization by <appro@openssl.org>:
19 #
20 #               this/original   with/without -DECP_NISTZ256_ASM(*)
21 # Opteron       +12-49%         +110-150%
22 # Bulldozer     +14-45%         +175-210%
23 # P4            +18-46%         n/a :-(
24 # Westmere      +12-34%         +80-87%
25 # Sandy Bridge  +9-35%          +110-120%
26 # Ivy Bridge    +9-35%          +110-125%
27 # Haswell       +8-37%          +140-160%
28 # Broadwell     +18-58%         +145-210%
29 # Atom          +15-50%         +130-180%
30 # VIA Nano      +43-160%        +300-480%
31 #
32 # (*)   "without -DECP_NISTZ256_ASM" refers to build with
33 #       "enable-ec_nistp_64_gcc_128";
34 #
35 # Ranges denote minimum and maximum improvement coefficients depending
36 # on benchmark. Lower coefficients are for ECDSA sign, relatively fastest
37 # server-side operation. Keep in mind that +100% means 2x improvement.
38
39 $flavour = shift;
40 $output  = shift;
41 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
42
43 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
44
45 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
46 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
47 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
48 die "can't locate x86_64-xlate.pl";
49
50 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
51 *STDOUT=*OUT;
52
53 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
54                 =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
55         $avx = ($1>=2.19) + ($1>=2.22);
56         $addx = ($1>=2.23);
57 }
58
59 if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
60             `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
61         $avx = ($1>=2.09) + ($1>=2.10);
62         $addx = ($1>=2.10);
63 }
64
65 if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
66             `ml64 2>&1` =~ /Version ([0-9]+)\./) {
67         $avx = ($1>=10) + ($1>=11);
68         $addx = ($1>=12);
69 }
70
71 if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) {
72         my $ver = $2 + $3/100.0;        # 3.1->3.01, 3.10->3.10
73         $avx = ($ver>=3.0) + ($ver>=3.01);
74         $addx = ($ver>=3.03);
75 }
76
77 $code.=<<___;
78 .text
79 .extern OPENSSL_ia32cap_P
80
81 # The polynomial
82 .align 64
83 .Lpoly:
84 .quad 0xffffffffffffffff, 0x00000000ffffffff, 0x0000000000000000, 0xffffffff00000001
85
86 # 2^512 mod P precomputed for NIST P256 polynomial
87 .LRR:
88 .quad 0x0000000000000003, 0xfffffffbffffffff, 0xfffffffffffffffe, 0x00000004fffffffd
89
90 .LOne:
91 .long 1,1,1,1,1,1,1,1
92 .LTwo:
93 .long 2,2,2,2,2,2,2,2
94 .LThree:
95 .long 3,3,3,3,3,3,3,3
96 .LONE_mont:
97 .quad 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe
98 ___
99
100 {
101 ################################################################################
102 # void ecp_nistz256_mul_by_2(uint64_t res[4], uint64_t a[4]);
103
104 my ($a0,$a1,$a2,$a3)=map("%r$_",(8..11));
105 my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rdx","%rcx","%r12","%r13");
106 my ($r_ptr,$a_ptr,$b_ptr)=("%rdi","%rsi","%rdx");
107
108 $code.=<<___;
109
110 .globl  ecp_nistz256_mul_by_2
111 .type   ecp_nistz256_mul_by_2,\@function,2
112 .align  64
113 ecp_nistz256_mul_by_2:
114 .cfi_startproc
115         push    %r12
116 .cfi_push       %r12
117         push    %r13
118 .cfi_push       %r13
119 .Lmul_by_2_body:
120
121         mov     8*0($a_ptr), $a0
122         xor     $t4,$t4
123         mov     8*1($a_ptr), $a1
124         add     $a0, $a0                # a0:a3+a0:a3
125         mov     8*2($a_ptr), $a2
126         adc     $a1, $a1
127         mov     8*3($a_ptr), $a3
128         lea     .Lpoly(%rip), $a_ptr
129          mov    $a0, $t0
130         adc     $a2, $a2
131         adc     $a3, $a3
132          mov    $a1, $t1
133         adc     \$0, $t4
134
135         sub     8*0($a_ptr), $a0
136          mov    $a2, $t2
137         sbb     8*1($a_ptr), $a1
138         sbb     8*2($a_ptr), $a2
139          mov    $a3, $t3
140         sbb     8*3($a_ptr), $a3
141         sbb     \$0, $t4
142
143         cmovc   $t0, $a0
144         cmovc   $t1, $a1
145         mov     $a0, 8*0($r_ptr)
146         cmovc   $t2, $a2
147         mov     $a1, 8*1($r_ptr)
148         cmovc   $t3, $a3
149         mov     $a2, 8*2($r_ptr)
150         mov     $a3, 8*3($r_ptr)
151
152         mov     0(%rsp),%r13
153 .cfi_restore    %r13
154         mov     8(%rsp),%r12
155 .cfi_restore    %r12
156         lea     16(%rsp),%rsp
157 .cfi_adjust_cfa_offset  -16
158 .Lmul_by_2_epilogue:
159         ret
160 .cfi_endproc
161 .size   ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2
162
163 ################################################################################
164 # void ecp_nistz256_div_by_2(uint64_t res[4], uint64_t a[4]);
165 .globl  ecp_nistz256_div_by_2
166 .type   ecp_nistz256_div_by_2,\@function,2
167 .align  32
168 ecp_nistz256_div_by_2:
169 .cfi_startproc
170         push    %r12
171 .cfi_push       %r12
172         push    %r13
173 .cfi_push       %r13
174 .Ldiv_by_2_body:
175
176         mov     8*0($a_ptr), $a0
177         mov     8*1($a_ptr), $a1
178         mov     8*2($a_ptr), $a2
179          mov    $a0, $t0
180         mov     8*3($a_ptr), $a3
181         lea     .Lpoly(%rip), $a_ptr
182
183          mov    $a1, $t1
184         xor     $t4, $t4
185         add     8*0($a_ptr), $a0
186          mov    $a2, $t2
187         adc     8*1($a_ptr), $a1
188         adc     8*2($a_ptr), $a2
189          mov    $a3, $t3
190         adc     8*3($a_ptr), $a3
191         adc     \$0, $t4
192         xor     $a_ptr, $a_ptr          # borrow $a_ptr
193         test    \$1, $t0
194
195         cmovz   $t0, $a0
196         cmovz   $t1, $a1
197         cmovz   $t2, $a2
198         cmovz   $t3, $a3
199         cmovz   $a_ptr, $t4
200
201         mov     $a1, $t0                # a0:a3>>1
202         shr     \$1, $a0
203         shl     \$63, $t0
204         mov     $a2, $t1
205         shr     \$1, $a1
206         or      $t0, $a0
207         shl     \$63, $t1
208         mov     $a3, $t2
209         shr     \$1, $a2
210         or      $t1, $a1
211         shl     \$63, $t2
212         shr     \$1, $a3
213         shl     \$63, $t4
214         or      $t2, $a2
215         or      $t4, $a3
216
217         mov     $a0, 8*0($r_ptr)
218         mov     $a1, 8*1($r_ptr)
219         mov     $a2, 8*2($r_ptr)
220         mov     $a3, 8*3($r_ptr)
221
222         mov     0(%rsp),%r13
223 .cfi_restore    %r13
224         mov     8(%rsp),%r12
225 .cfi_restore    %r12
226         lea     16(%rsp),%rsp
227 .cfi_adjust_cfa_offset  -16
228 .Ldiv_by_2_epilogue:
229         ret
230 .cfi_endproc
231 .size   ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2
232
233 ################################################################################
234 # void ecp_nistz256_mul_by_3(uint64_t res[4], uint64_t a[4]);
235 .globl  ecp_nistz256_mul_by_3
236 .type   ecp_nistz256_mul_by_3,\@function,2
237 .align  32
238 ecp_nistz256_mul_by_3:
239 .cfi_startproc
240         push    %r12
241 .cfi_push       %r12
242         push    %r13
243 .cfi_push       %r13
244 .Lmul_by_3_body:
245
246         mov     8*0($a_ptr), $a0
247         xor     $t4, $t4
248         mov     8*1($a_ptr), $a1
249         add     $a0, $a0                # a0:a3+a0:a3
250         mov     8*2($a_ptr), $a2
251         adc     $a1, $a1
252         mov     8*3($a_ptr), $a3
253          mov    $a0, $t0
254         adc     $a2, $a2
255         adc     $a3, $a3
256          mov    $a1, $t1
257         adc     \$0, $t4
258
259         sub     \$-1, $a0
260          mov    $a2, $t2
261         sbb     .Lpoly+8*1(%rip), $a1
262         sbb     \$0, $a2
263          mov    $a3, $t3
264         sbb     .Lpoly+8*3(%rip), $a3
265         sbb     \$0, $t4
266
267         cmovc   $t0, $a0
268         cmovc   $t1, $a1
269         cmovc   $t2, $a2
270         cmovc   $t3, $a3
271
272         xor     $t4, $t4
273         add     8*0($a_ptr), $a0        # a0:a3+=a_ptr[0:3]
274         adc     8*1($a_ptr), $a1
275          mov    $a0, $t0
276         adc     8*2($a_ptr), $a2
277         adc     8*3($a_ptr), $a3
278          mov    $a1, $t1
279         adc     \$0, $t4
280
281         sub     \$-1, $a0
282          mov    $a2, $t2
283         sbb     .Lpoly+8*1(%rip), $a1
284         sbb     \$0, $a2
285          mov    $a3, $t3
286         sbb     .Lpoly+8*3(%rip), $a3
287         sbb     \$0, $t4
288
289         cmovc   $t0, $a0
290         cmovc   $t1, $a1
291         mov     $a0, 8*0($r_ptr)
292         cmovc   $t2, $a2
293         mov     $a1, 8*1($r_ptr)
294         cmovc   $t3, $a3
295         mov     $a2, 8*2($r_ptr)
296         mov     $a3, 8*3($r_ptr)
297
298         mov     0(%rsp),%r13
299 .cfi_restore    %r13
300         mov     8(%rsp),%r12
301 .cfi_restore    %r12
302         lea     16(%rsp),%rsp
303 .cfi_adjust_cfa_offset  -16
304 .Lmul_by_3_epilogue:
305         ret
306 .cfi_endproc
307 .size   ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3
308
309 ################################################################################
310 # void ecp_nistz256_add(uint64_t res[4], uint64_t a[4], uint64_t b[4]);
311 .globl  ecp_nistz256_add
312 .type   ecp_nistz256_add,\@function,3
313 .align  32
314 ecp_nistz256_add:
315 .cfi_startproc
316         push    %r12
317 .cfi_push       %r12
318         push    %r13
319 .cfi_push       %r13
320 .Ladd_body:
321
322         mov     8*0($a_ptr), $a0
323         xor     $t4, $t4
324         mov     8*1($a_ptr), $a1
325         mov     8*2($a_ptr), $a2
326         mov     8*3($a_ptr), $a3
327         lea     .Lpoly(%rip), $a_ptr
328
329         add     8*0($b_ptr), $a0
330         adc     8*1($b_ptr), $a1
331          mov    $a0, $t0
332         adc     8*2($b_ptr), $a2
333         adc     8*3($b_ptr), $a3
334          mov    $a1, $t1
335         adc     \$0, $t4
336
337         sub     8*0($a_ptr), $a0
338          mov    $a2, $t2
339         sbb     8*1($a_ptr), $a1
340         sbb     8*2($a_ptr), $a2
341          mov    $a3, $t3
342         sbb     8*3($a_ptr), $a3
343         sbb     \$0, $t4
344
345         cmovc   $t0, $a0
346         cmovc   $t1, $a1
347         mov     $a0, 8*0($r_ptr)
348         cmovc   $t2, $a2
349         mov     $a1, 8*1($r_ptr)
350         cmovc   $t3, $a3
351         mov     $a2, 8*2($r_ptr)
352         mov     $a3, 8*3($r_ptr)
353
354         mov     0(%rsp),%r13
355 .cfi_restore    %r13
356         mov     8(%rsp),%r12
357 .cfi_restore    %r12
358         lea     16(%rsp),%rsp
359 .cfi_adjust_cfa_offset  -16
360 .Ladd_epilogue:
361         ret
362 .cfi_endproc
363 .size   ecp_nistz256_add,.-ecp_nistz256_add
364
365 ################################################################################
366 # void ecp_nistz256_sub(uint64_t res[4], uint64_t a[4], uint64_t b[4]);
367 .globl  ecp_nistz256_sub
368 .type   ecp_nistz256_sub,\@function,3
369 .align  32
370 ecp_nistz256_sub:
371 .cfi_startproc
372         push    %r12
373 .cfi_push       %r12
374         push    %r13
375 .cfi_push       %r13
376 .Lsub_body:
377
378         mov     8*0($a_ptr), $a0
379         xor     $t4, $t4
380         mov     8*1($a_ptr), $a1
381         mov     8*2($a_ptr), $a2
382         mov     8*3($a_ptr), $a3
383         lea     .Lpoly(%rip), $a_ptr
384
385         sub     8*0($b_ptr), $a0
386         sbb     8*1($b_ptr), $a1
387          mov    $a0, $t0
388         sbb     8*2($b_ptr), $a2
389         sbb     8*3($b_ptr), $a3
390          mov    $a1, $t1
391         sbb     \$0, $t4
392
393         add     8*0($a_ptr), $a0
394          mov    $a2, $t2
395         adc     8*1($a_ptr), $a1
396         adc     8*2($a_ptr), $a2
397          mov    $a3, $t3
398         adc     8*3($a_ptr), $a3
399         test    $t4, $t4
400
401         cmovz   $t0, $a0
402         cmovz   $t1, $a1
403         mov     $a0, 8*0($r_ptr)
404         cmovz   $t2, $a2
405         mov     $a1, 8*1($r_ptr)
406         cmovz   $t3, $a3
407         mov     $a2, 8*2($r_ptr)
408         mov     $a3, 8*3($r_ptr)
409
410         mov     0(%rsp),%r13
411 .cfi_restore    %r13
412         mov     8(%rsp),%r12
413 .cfi_restore    %r12
414         lea     16(%rsp),%rsp
415 .cfi_adjust_cfa_offset  -16
416 .Lsub_epilogue:
417         ret
418 .cfi_endproc
419 .size   ecp_nistz256_sub,.-ecp_nistz256_sub
420
421 ################################################################################
422 # void ecp_nistz256_neg(uint64_t res[4], uint64_t a[4]);
423 .globl  ecp_nistz256_neg
424 .type   ecp_nistz256_neg,\@function,2
425 .align  32
426 ecp_nistz256_neg:
427 .cfi_startproc
428         push    %r12
429 .cfi_push       %r12
430         push    %r13
431 .cfi_push       %r13
432 .Lneg_body:
433
434         xor     $a0, $a0
435         xor     $a1, $a1
436         xor     $a2, $a2
437         xor     $a3, $a3
438         xor     $t4, $t4
439
440         sub     8*0($a_ptr), $a0
441         sbb     8*1($a_ptr), $a1
442         sbb     8*2($a_ptr), $a2
443          mov    $a0, $t0
444         sbb     8*3($a_ptr), $a3
445         lea     .Lpoly(%rip), $a_ptr
446          mov    $a1, $t1
447         sbb     \$0, $t4
448
449         add     8*0($a_ptr), $a0
450          mov    $a2, $t2
451         adc     8*1($a_ptr), $a1
452         adc     8*2($a_ptr), $a2
453          mov    $a3, $t3
454         adc     8*3($a_ptr), $a3
455         test    $t4, $t4
456
457         cmovz   $t0, $a0
458         cmovz   $t1, $a1
459         mov     $a0, 8*0($r_ptr)
460         cmovz   $t2, $a2
461         mov     $a1, 8*1($r_ptr)
462         cmovz   $t3, $a3
463         mov     $a2, 8*2($r_ptr)
464         mov     $a3, 8*3($r_ptr)
465
466         mov     0(%rsp),%r13
467 .cfi_restore    %r13
468         mov     8(%rsp),%r12
469 .cfi_restore    %r12
470         lea     16(%rsp),%rsp
471 .cfi_adjust_cfa_offset  -16
472 .Lneg_epilogue:
473         ret
474 .cfi_endproc
475 .size   ecp_nistz256_neg,.-ecp_nistz256_neg
476 ___
477 }
478 {
479 my ($r_ptr,$a_ptr,$b_org,$b_ptr)=("%rdi","%rsi","%rdx","%rbx");
480 my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("%r$_",(8..15));
481 my ($t0,$t1,$t2,$t3,$t4)=("%rcx","%rbp","%rbx","%rdx","%rax");
482 my ($poly1,$poly3)=($acc6,$acc7);
483
484 $code.=<<___;
485 ################################################################################
486 # void ecp_nistz256_to_mont(
487 #   uint64_t res[4],
488 #   uint64_t in[4]);
489 .globl  ecp_nistz256_to_mont
490 .type   ecp_nistz256_to_mont,\@function,2
491 .align  32
492 ecp_nistz256_to_mont:
493 ___
494 $code.=<<___    if ($addx);
495         mov     \$0x80100, %ecx
496         and     OPENSSL_ia32cap_P+8(%rip), %ecx
497 ___
498 $code.=<<___;
499         lea     .LRR(%rip), $b_org
500         jmp     .Lmul_mont
501 .size   ecp_nistz256_to_mont,.-ecp_nistz256_to_mont
502
503 ################################################################################
504 # void ecp_nistz256_mul_mont(
505 #   uint64_t res[4],
506 #   uint64_t a[4],
507 #   uint64_t b[4]);
508
509 .globl  ecp_nistz256_mul_mont
510 .type   ecp_nistz256_mul_mont,\@function,3
511 .align  32
512 ecp_nistz256_mul_mont:
513 .cfi_startproc
514 ___
515 $code.=<<___    if ($addx);
516         mov     \$0x80100, %ecx
517         and     OPENSSL_ia32cap_P+8(%rip), %ecx
518 ___
519 $code.=<<___;
520 .Lmul_mont:
521         push    %rbp
522 .cfi_push       %rbp
523         push    %rbx
524 .cfi_push       %rbx
525         push    %r12
526 .cfi_push       %r12
527         push    %r13
528 .cfi_push       %r13
529         push    %r14
530 .cfi_push       %r14
531         push    %r15
532 .cfi_push       %r15
533 .Lmul_body:
534 ___
535 $code.=<<___    if ($addx);
536         cmp     \$0x80100, %ecx
537         je      .Lmul_montx
538 ___
539 $code.=<<___;
540         mov     $b_org, $b_ptr
541         mov     8*0($b_org), %rax
542         mov     8*0($a_ptr), $acc1
543         mov     8*1($a_ptr), $acc2
544         mov     8*2($a_ptr), $acc3
545         mov     8*3($a_ptr), $acc4
546
547         call    __ecp_nistz256_mul_montq
548 ___
549 $code.=<<___    if ($addx);
550         jmp     .Lmul_mont_done
551
552 .align  32
553 .Lmul_montx:
554         mov     $b_org, $b_ptr
555         mov     8*0($b_org), %rdx
556         mov     8*0($a_ptr), $acc1
557         mov     8*1($a_ptr), $acc2
558         mov     8*2($a_ptr), $acc3
559         mov     8*3($a_ptr), $acc4
560         lea     -128($a_ptr), $a_ptr    # control u-op density
561
562         call    __ecp_nistz256_mul_montx
563 ___
564 $code.=<<___;
565 .Lmul_mont_done:
566         mov     0(%rsp),%r15
567 .cfi_restore    %r15
568         mov     8(%rsp),%r14
569 .cfi_restore    %r14
570         mov     16(%rsp),%r13
571 .cfi_restore    %r13
572         mov     24(%rsp),%r12
573 .cfi_restore    %r12
574         mov     32(%rsp),%rbx
575 .cfi_restore    %rbx
576         mov     40(%rsp),%rbp
577 .cfi_restore    %rbp
578         lea     48(%rsp),%rsp
579 .cfi_adjust_cfa_offset  -48
580 .Lmul_epilogue:
581         ret
582 .cfi_endproc
583 .size   ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont
584
585 .type   __ecp_nistz256_mul_montq,\@abi-omnipotent
586 .align  32
587 __ecp_nistz256_mul_montq:
588         ########################################################################
589         # Multiply a by b[0]
590         mov     %rax, $t1
591         mulq    $acc1
592         mov     .Lpoly+8*1(%rip),$poly1
593         mov     %rax, $acc0
594         mov     $t1, %rax
595         mov     %rdx, $acc1
596
597         mulq    $acc2
598         mov     .Lpoly+8*3(%rip),$poly3
599         add     %rax, $acc1
600         mov     $t1, %rax
601         adc     \$0, %rdx
602         mov     %rdx, $acc2
603
604         mulq    $acc3
605         add     %rax, $acc2
606         mov     $t1, %rax
607         adc     \$0, %rdx
608         mov     %rdx, $acc3
609
610         mulq    $acc4
611         add     %rax, $acc3
612          mov    $acc0, %rax
613         adc     \$0, %rdx
614         xor     $acc5, $acc5
615         mov     %rdx, $acc4
616
617         ########################################################################
618         # First reduction step
619         # Basically now we want to multiply acc[0] by p256,
620         # and add the result to the acc.
621         # Due to the special form of p256 we do some optimizations
622         #
623         # acc[0] x p256[0..1] = acc[0] x 2^96 - acc[0]
624         # then we add acc[0] and get acc[0] x 2^96
625
626         mov     $acc0, $t1
627         shl     \$32, $acc0
628         mulq    $poly3
629         shr     \$32, $t1
630         add     $acc0, $acc1            # +=acc[0]<<96
631         adc     $t1, $acc2
632         adc     %rax, $acc3
633          mov    8*1($b_ptr), %rax
634         adc     %rdx, $acc4
635         adc     \$0, $acc5
636         xor     $acc0, $acc0
637
638         ########################################################################
639         # Multiply by b[1]
640         mov     %rax, $t1
641         mulq    8*0($a_ptr)
642         add     %rax, $acc1
643         mov     $t1, %rax
644         adc     \$0, %rdx
645         mov     %rdx, $t0
646
647         mulq    8*1($a_ptr)
648         add     $t0, $acc2
649         adc     \$0, %rdx
650         add     %rax, $acc2
651         mov     $t1, %rax
652         adc     \$0, %rdx
653         mov     %rdx, $t0
654
655         mulq    8*2($a_ptr)
656         add     $t0, $acc3
657         adc     \$0, %rdx
658         add     %rax, $acc3
659         mov     $t1, %rax
660         adc     \$0, %rdx
661         mov     %rdx, $t0
662
663         mulq    8*3($a_ptr)
664         add     $t0, $acc4
665         adc     \$0, %rdx
666         add     %rax, $acc4
667          mov    $acc1, %rax
668         adc     %rdx, $acc5
669         adc     \$0, $acc0
670
671         ########################################################################
672         # Second reduction step
673         mov     $acc1, $t1
674         shl     \$32, $acc1
675         mulq    $poly3
676         shr     \$32, $t1
677         add     $acc1, $acc2
678         adc     $t1, $acc3
679         adc     %rax, $acc4
680          mov    8*2($b_ptr), %rax
681         adc     %rdx, $acc5
682         adc     \$0, $acc0
683         xor     $acc1, $acc1
684
685         ########################################################################
686         # Multiply by b[2]
687         mov     %rax, $t1
688         mulq    8*0($a_ptr)
689         add     %rax, $acc2
690         mov     $t1, %rax
691         adc     \$0, %rdx
692         mov     %rdx, $t0
693
694         mulq    8*1($a_ptr)
695         add     $t0, $acc3
696         adc     \$0, %rdx
697         add     %rax, $acc3
698         mov     $t1, %rax
699         adc     \$0, %rdx
700         mov     %rdx, $t0
701
702         mulq    8*2($a_ptr)
703         add     $t0, $acc4
704         adc     \$0, %rdx
705         add     %rax, $acc4
706         mov     $t1, %rax
707         adc     \$0, %rdx
708         mov     %rdx, $t0
709
710         mulq    8*3($a_ptr)
711         add     $t0, $acc5
712         adc     \$0, %rdx
713         add     %rax, $acc5
714          mov    $acc2, %rax
715         adc     %rdx, $acc0
716         adc     \$0, $acc1
717
718         ########################################################################
719         # Third reduction step
720         mov     $acc2, $t1
721         shl     \$32, $acc2
722         mulq    $poly3
723         shr     \$32, $t1
724         add     $acc2, $acc3
725         adc     $t1, $acc4
726         adc     %rax, $acc5
727          mov    8*3($b_ptr), %rax
728         adc     %rdx, $acc0
729         adc     \$0, $acc1
730         xor     $acc2, $acc2
731
732         ########################################################################
733         # Multiply by b[3]
734         mov     %rax, $t1
735         mulq    8*0($a_ptr)
736         add     %rax, $acc3
737         mov     $t1, %rax
738         adc     \$0, %rdx
739         mov     %rdx, $t0
740
741         mulq    8*1($a_ptr)
742         add     $t0, $acc4
743         adc     \$0, %rdx
744         add     %rax, $acc4
745         mov     $t1, %rax
746         adc     \$0, %rdx
747         mov     %rdx, $t0
748
749         mulq    8*2($a_ptr)
750         add     $t0, $acc5
751         adc     \$0, %rdx
752         add     %rax, $acc5
753         mov     $t1, %rax
754         adc     \$0, %rdx
755         mov     %rdx, $t0
756
757         mulq    8*3($a_ptr)
758         add     $t0, $acc0
759         adc     \$0, %rdx
760         add     %rax, $acc0
761          mov    $acc3, %rax
762         adc     %rdx, $acc1
763         adc     \$0, $acc2
764
765         ########################################################################
766         # Final reduction step
767         mov     $acc3, $t1
768         shl     \$32, $acc3
769         mulq    $poly3
770         shr     \$32, $t1
771         add     $acc3, $acc4
772         adc     $t1, $acc5
773          mov    $acc4, $t0
774         adc     %rax, $acc0
775         adc     %rdx, $acc1
776          mov    $acc5, $t1
777         adc     \$0, $acc2
778
779         ########################################################################
780         # Branch-less conditional subtraction of P
781         sub     \$-1, $acc4             # .Lpoly[0]
782          mov    $acc0, $t2
783         sbb     $poly1, $acc5           # .Lpoly[1]
784         sbb     \$0, $acc0              # .Lpoly[2]
785          mov    $acc1, $t3
786         sbb     $poly3, $acc1           # .Lpoly[3]
787         sbb     \$0, $acc2
788
789         cmovc   $t0, $acc4
790         cmovc   $t1, $acc5
791         mov     $acc4, 8*0($r_ptr)
792         cmovc   $t2, $acc0
793         mov     $acc5, 8*1($r_ptr)
794         cmovc   $t3, $acc1
795         mov     $acc0, 8*2($r_ptr)
796         mov     $acc1, 8*3($r_ptr)
797
798         ret
799 .size   __ecp_nistz256_mul_montq,.-__ecp_nistz256_mul_montq
800
801 ################################################################################
802 # void ecp_nistz256_sqr_mont(
803 #   uint64_t res[4],
804 #   uint64_t a[4]);
805
806 # we optimize the square according to S.Gueron and V.Krasnov,
807 # "Speeding up Big-Number Squaring"
808 .globl  ecp_nistz256_sqr_mont
809 .type   ecp_nistz256_sqr_mont,\@function,2
810 .align  32
811 ecp_nistz256_sqr_mont:
812 .cfi_startproc
813 ___
814 $code.=<<___    if ($addx);
815         mov     \$0x80100, %ecx
816         and     OPENSSL_ia32cap_P+8(%rip), %ecx
817 ___
818 $code.=<<___;
819         push    %rbp
820 .cfi_push       %rbp
821         push    %rbx
822 .cfi_push       %rbx
823         push    %r12
824 .cfi_push       %r12
825         push    %r13
826 .cfi_push       %r13
827         push    %r14
828 .cfi_push       %r14
829         push    %r15
830 .cfi_push       %r15
831 .Lsqr_body:
832 ___
833 $code.=<<___    if ($addx);
834         cmp     \$0x80100, %ecx
835         je      .Lsqr_montx
836 ___
837 $code.=<<___;
838         mov     8*0($a_ptr), %rax
839         mov     8*1($a_ptr), $acc6
840         mov     8*2($a_ptr), $acc7
841         mov     8*3($a_ptr), $acc0
842
843         call    __ecp_nistz256_sqr_montq
844 ___
845 $code.=<<___    if ($addx);
846         jmp     .Lsqr_mont_done
847
848 .align  32
849 .Lsqr_montx:
850         mov     8*0($a_ptr), %rdx
851         mov     8*1($a_ptr), $acc6
852         mov     8*2($a_ptr), $acc7
853         mov     8*3($a_ptr), $acc0
854         lea     -128($a_ptr), $a_ptr    # control u-op density
855
856         call    __ecp_nistz256_sqr_montx
857 ___
858 $code.=<<___;
859 .Lsqr_mont_done:
860         mov     0(%rsp),%r15
861 .cfi_restore    %r15
862         mov     8(%rsp),%r14
863 .cfi_restore    %r14
864         mov     16(%rsp),%r13
865 .cfi_restore    %r13
866         mov     24(%rsp),%r12
867 .cfi_restore    %r12
868         mov     32(%rsp),%rbx
869 .cfi_restore    %rbx
870         mov     40(%rsp),%rbp
871 .cfi_restore    %rbp
872         lea     48(%rsp),%rsp
873 .cfi_adjust_cfa_offset  -48
874 .Lsqr_epilogue:
875         ret
876 .cfi_endproc
877 .size   ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont
878
879 .type   __ecp_nistz256_sqr_montq,\@abi-omnipotent
880 .align  32
881 __ecp_nistz256_sqr_montq:
882         mov     %rax, $acc5
883         mulq    $acc6                   # a[1]*a[0]
884         mov     %rax, $acc1
885         mov     $acc7, %rax
886         mov     %rdx, $acc2
887
888         mulq    $acc5                   # a[0]*a[2]
889         add     %rax, $acc2
890         mov     $acc0, %rax
891         adc     \$0, %rdx
892         mov     %rdx, $acc3
893
894         mulq    $acc5                   # a[0]*a[3]
895         add     %rax, $acc3
896          mov    $acc7, %rax
897         adc     \$0, %rdx
898         mov     %rdx, $acc4
899
900         #################################
901         mulq    $acc6                   # a[1]*a[2]
902         add     %rax, $acc3
903         mov     $acc0, %rax
904         adc     \$0, %rdx
905         mov     %rdx, $t1
906
907         mulq    $acc6                   # a[1]*a[3]
908         add     %rax, $acc4
909          mov    $acc0, %rax
910         adc     \$0, %rdx
911         add     $t1, $acc4
912         mov     %rdx, $acc5
913         adc     \$0, $acc5
914
915         #################################
916         mulq    $acc7                   # a[2]*a[3]
917         xor     $acc7, $acc7
918         add     %rax, $acc5
919          mov    8*0($a_ptr), %rax
920         mov     %rdx, $acc6
921         adc     \$0, $acc6
922
923         add     $acc1, $acc1            # acc1:6<<1
924         adc     $acc2, $acc2
925         adc     $acc3, $acc3
926         adc     $acc4, $acc4
927         adc     $acc5, $acc5
928         adc     $acc6, $acc6
929         adc     \$0, $acc7
930
931         mulq    %rax
932         mov     %rax, $acc0
933         mov     8*1($a_ptr), %rax
934         mov     %rdx, $t0
935
936         mulq    %rax
937         add     $t0, $acc1
938         adc     %rax, $acc2
939         mov     8*2($a_ptr), %rax
940         adc     \$0, %rdx
941         mov     %rdx, $t0
942
943         mulq    %rax
944         add     $t0, $acc3
945         adc     %rax, $acc4
946         mov     8*3($a_ptr), %rax
947         adc     \$0, %rdx
948         mov     %rdx, $t0
949
950         mulq    %rax
951         add     $t0, $acc5
952         adc     %rax, $acc6
953          mov    $acc0, %rax
954         adc     %rdx, $acc7
955
956         mov     .Lpoly+8*1(%rip), $a_ptr
957         mov     .Lpoly+8*3(%rip), $t1
958
959         ##########################################
960         # Now the reduction
961         # First iteration
962         mov     $acc0, $t0
963         shl     \$32, $acc0
964         mulq    $t1
965         shr     \$32, $t0
966         add     $acc0, $acc1            # +=acc[0]<<96
967         adc     $t0, $acc2
968         adc     %rax, $acc3
969          mov    $acc1, %rax
970         adc     \$0, %rdx
971
972         ##########################################
973         # Second iteration
974         mov     $acc1, $t0
975         shl     \$32, $acc1
976         mov     %rdx, $acc0
977         mulq    $t1
978         shr     \$32, $t0
979         add     $acc1, $acc2
980         adc     $t0, $acc3
981         adc     %rax, $acc0
982          mov    $acc2, %rax
983         adc     \$0, %rdx
984
985         ##########################################
986         # Third iteration
987         mov     $acc2, $t0
988         shl     \$32, $acc2
989         mov     %rdx, $acc1
990         mulq    $t1
991         shr     \$32, $t0
992         add     $acc2, $acc3
993         adc     $t0, $acc0
994         adc     %rax, $acc1
995          mov    $acc3, %rax
996         adc     \$0, %rdx
997
998         ###########################################
999         # Last iteration
1000         mov     $acc3, $t0
1001         shl     \$32, $acc3
1002         mov     %rdx, $acc2
1003         mulq    $t1
1004         shr     \$32, $t0
1005         add     $acc3, $acc0
1006         adc     $t0, $acc1
1007         adc     %rax, $acc2
1008         adc     \$0, %rdx
1009         xor     $acc3, $acc3
1010
1011         ############################################
1012         # Add the rest of the acc
1013         add     $acc0, $acc4
1014         adc     $acc1, $acc5
1015          mov    $acc4, $acc0
1016         adc     $acc2, $acc6
1017         adc     %rdx, $acc7
1018          mov    $acc5, $acc1
1019         adc     \$0, $acc3
1020
1021         sub     \$-1, $acc4             # .Lpoly[0]
1022          mov    $acc6, $acc2
1023         sbb     $a_ptr, $acc5           # .Lpoly[1]
1024         sbb     \$0, $acc6              # .Lpoly[2]
1025          mov    $acc7, $t0
1026         sbb     $t1, $acc7              # .Lpoly[3]
1027         sbb     \$0, $acc3
1028
1029         cmovc   $acc0, $acc4
1030         cmovc   $acc1, $acc5
1031         mov     $acc4, 8*0($r_ptr)
1032         cmovc   $acc2, $acc6
1033         mov     $acc5, 8*1($r_ptr)
1034         cmovc   $t0, $acc7
1035         mov     $acc6, 8*2($r_ptr)
1036         mov     $acc7, 8*3($r_ptr)
1037
1038         ret
1039 .size   __ecp_nistz256_sqr_montq,.-__ecp_nistz256_sqr_montq
1040 ___
1041
1042 if ($addx) {
1043 $code.=<<___;
1044 .type   __ecp_nistz256_mul_montx,\@abi-omnipotent
1045 .align  32
1046 __ecp_nistz256_mul_montx:
1047         ########################################################################
1048         # Multiply by b[0]
1049         mulx    $acc1, $acc0, $acc1
1050         mulx    $acc2, $t0, $acc2
1051         mov     \$32, $poly1
1052         xor     $acc5, $acc5            # cf=0
1053         mulx    $acc3, $t1, $acc3
1054         mov     .Lpoly+8*3(%rip), $poly3
1055         adc     $t0, $acc1
1056         mulx    $acc4, $t0, $acc4
1057          mov    $acc0, %rdx
1058         adc     $t1, $acc2
1059          shlx   $poly1,$acc0,$t1
1060         adc     $t0, $acc3
1061          shrx   $poly1,$acc0,$t0
1062         adc     \$0, $acc4
1063
1064         ########################################################################
1065         # First reduction step
1066         add     $t1, $acc1
1067         adc     $t0, $acc2
1068
1069         mulx    $poly3, $t0, $t1
1070          mov    8*1($b_ptr), %rdx
1071         adc     $t0, $acc3
1072         adc     $t1, $acc4
1073         adc     \$0, $acc5
1074         xor     $acc0, $acc0            # $acc0=0,cf=0,of=0
1075
1076         ########################################################################
1077         # Multiply by b[1]
1078         mulx    8*0+128($a_ptr), $t0, $t1
1079         adcx    $t0, $acc1
1080         adox    $t1, $acc2
1081
1082         mulx    8*1+128($a_ptr), $t0, $t1
1083         adcx    $t0, $acc2
1084         adox    $t1, $acc3
1085
1086         mulx    8*2+128($a_ptr), $t0, $t1
1087         adcx    $t0, $acc3
1088         adox    $t1, $acc4
1089
1090         mulx    8*3+128($a_ptr), $t0, $t1
1091          mov    $acc1, %rdx
1092         adcx    $t0, $acc4
1093          shlx   $poly1, $acc1, $t0
1094         adox    $t1, $acc5
1095          shrx   $poly1, $acc1, $t1
1096
1097         adcx    $acc0, $acc5
1098         adox    $acc0, $acc0
1099         adc     \$0, $acc0
1100
1101         ########################################################################
1102         # Second reduction step
1103         add     $t0, $acc2
1104         adc     $t1, $acc3
1105
1106         mulx    $poly3, $t0, $t1
1107          mov    8*2($b_ptr), %rdx
1108         adc     $t0, $acc4
1109         adc     $t1, $acc5
1110         adc     \$0, $acc0
1111         xor     $acc1 ,$acc1            # $acc1=0,cf=0,of=0
1112
1113         ########################################################################
1114         # Multiply by b[2]
1115         mulx    8*0+128($a_ptr), $t0, $t1
1116         adcx    $t0, $acc2
1117         adox    $t1, $acc3
1118
1119         mulx    8*1+128($a_ptr), $t0, $t1
1120         adcx    $t0, $acc3
1121         adox    $t1, $acc4
1122
1123         mulx    8*2+128($a_ptr), $t0, $t1
1124         adcx    $t0, $acc4
1125         adox    $t1, $acc5
1126
1127         mulx    8*3+128($a_ptr), $t0, $t1
1128          mov    $acc2, %rdx
1129         adcx    $t0, $acc5
1130          shlx   $poly1, $acc2, $t0
1131         adox    $t1, $acc0
1132          shrx   $poly1, $acc2, $t1
1133
1134         adcx    $acc1, $acc0
1135         adox    $acc1, $acc1
1136         adc     \$0, $acc1
1137
1138         ########################################################################
1139         # Third reduction step
1140         add     $t0, $acc3
1141         adc     $t1, $acc4
1142
1143         mulx    $poly3, $t0, $t1
1144          mov    8*3($b_ptr), %rdx
1145         adc     $t0, $acc5
1146         adc     $t1, $acc0
1147         adc     \$0, $acc1
1148         xor     $acc2, $acc2            # $acc2=0,cf=0,of=0
1149
1150         ########################################################################
1151         # Multiply by b[3]
1152         mulx    8*0+128($a_ptr), $t0, $t1
1153         adcx    $t0, $acc3
1154         adox    $t1, $acc4
1155
1156         mulx    8*1+128($a_ptr), $t0, $t1
1157         adcx    $t0, $acc4
1158         adox    $t1, $acc5
1159
1160         mulx    8*2+128($a_ptr), $t0, $t1
1161         adcx    $t0, $acc5
1162         adox    $t1, $acc0
1163
1164         mulx    8*3+128($a_ptr), $t0, $t1
1165          mov    $acc3, %rdx
1166         adcx    $t0, $acc0
1167          shlx   $poly1, $acc3, $t0
1168         adox    $t1, $acc1
1169          shrx   $poly1, $acc3, $t1
1170
1171         adcx    $acc2, $acc1
1172         adox    $acc2, $acc2
1173         adc     \$0, $acc2
1174
1175         ########################################################################
1176         # Fourth reduction step
1177         add     $t0, $acc4
1178         adc     $t1, $acc5
1179
1180         mulx    $poly3, $t0, $t1
1181          mov    $acc4, $t2
1182         mov     .Lpoly+8*1(%rip), $poly1
1183         adc     $t0, $acc0
1184          mov    $acc5, $t3
1185         adc     $t1, $acc1
1186         adc     \$0, $acc2
1187
1188         ########################################################################
1189         # Branch-less conditional subtraction of P
1190         xor     %eax, %eax
1191          mov    $acc0, $t0
1192         sbb     \$-1, $acc4             # .Lpoly[0]
1193         sbb     $poly1, $acc5           # .Lpoly[1]
1194         sbb     \$0, $acc0              # .Lpoly[2]
1195          mov    $acc1, $t1
1196         sbb     $poly3, $acc1           # .Lpoly[3]
1197         sbb     \$0, $acc2
1198
1199         cmovc   $t2, $acc4
1200         cmovc   $t3, $acc5
1201         mov     $acc4, 8*0($r_ptr)
1202         cmovc   $t0, $acc0
1203         mov     $acc5, 8*1($r_ptr)
1204         cmovc   $t1, $acc1
1205         mov     $acc0, 8*2($r_ptr)
1206         mov     $acc1, 8*3($r_ptr)
1207
1208         ret
1209 .size   __ecp_nistz256_mul_montx,.-__ecp_nistz256_mul_montx
1210
1211 .type   __ecp_nistz256_sqr_montx,\@abi-omnipotent
1212 .align  32
1213 __ecp_nistz256_sqr_montx:
1214         mulx    $acc6, $acc1, $acc2     # a[0]*a[1]
1215         mulx    $acc7, $t0, $acc3       # a[0]*a[2]
1216         xor     %eax, %eax
1217         adc     $t0, $acc2
1218         mulx    $acc0, $t1, $acc4       # a[0]*a[3]
1219          mov    $acc6, %rdx
1220         adc     $t1, $acc3
1221         adc     \$0, $acc4
1222         xor     $acc5, $acc5            # $acc5=0,cf=0,of=0
1223
1224         #################################
1225         mulx    $acc7, $t0, $t1         # a[1]*a[2]
1226         adcx    $t0, $acc3
1227         adox    $t1, $acc4
1228
1229         mulx    $acc0, $t0, $t1         # a[1]*a[3]
1230          mov    $acc7, %rdx
1231         adcx    $t0, $acc4
1232         adox    $t1, $acc5
1233         adc     \$0, $acc5
1234
1235         #################################
1236         mulx    $acc0, $t0, $acc6       # a[2]*a[3]
1237          mov    8*0+128($a_ptr), %rdx
1238         xor     $acc7, $acc7            # $acc7=0,cf=0,of=0
1239          adcx   $acc1, $acc1            # acc1:6<<1
1240         adox    $t0, $acc5
1241          adcx   $acc2, $acc2
1242         adox    $acc7, $acc6            # of=0
1243
1244         mulx    %rdx, $acc0, $t1
1245         mov     8*1+128($a_ptr), %rdx
1246          adcx   $acc3, $acc3
1247         adox    $t1, $acc1
1248          adcx   $acc4, $acc4
1249         mulx    %rdx, $t0, $t4
1250         mov     8*2+128($a_ptr), %rdx
1251          adcx   $acc5, $acc5
1252         adox    $t0, $acc2
1253          adcx   $acc6, $acc6
1254         .byte   0x67
1255         mulx    %rdx, $t0, $t1
1256         mov     8*3+128($a_ptr), %rdx
1257         adox    $t4, $acc3
1258          adcx   $acc7, $acc7
1259         adox    $t0, $acc4
1260          mov    \$32, $a_ptr
1261         adox    $t1, $acc5
1262         .byte   0x67,0x67
1263         mulx    %rdx, $t0, $t4
1264          mov    .Lpoly+8*3(%rip), %rdx
1265         adox    $t0, $acc6
1266          shlx   $a_ptr, $acc0, $t0
1267         adox    $t4, $acc7
1268          shrx   $a_ptr, $acc0, $t4
1269         mov     %rdx,$t1
1270
1271         # reduction step 1
1272         add     $t0, $acc1
1273         adc     $t4, $acc2
1274
1275         mulx    $acc0, $t0, $acc0
1276         adc     $t0, $acc3
1277          shlx   $a_ptr, $acc1, $t0
1278         adc     \$0, $acc0
1279          shrx   $a_ptr, $acc1, $t4
1280
1281         # reduction step 2
1282         add     $t0, $acc2
1283         adc     $t4, $acc3
1284
1285         mulx    $acc1, $t0, $acc1
1286         adc     $t0, $acc0
1287          shlx   $a_ptr, $acc2, $t0
1288         adc     \$0, $acc1
1289          shrx   $a_ptr, $acc2, $t4
1290
1291         # reduction step 3
1292         add     $t0, $acc3
1293         adc     $t4, $acc0
1294
1295         mulx    $acc2, $t0, $acc2
1296         adc     $t0, $acc1
1297          shlx   $a_ptr, $acc3, $t0
1298         adc     \$0, $acc2
1299          shrx   $a_ptr, $acc3, $t4
1300
1301         # reduction step 4
1302         add     $t0, $acc0
1303         adc     $t4, $acc1
1304
1305         mulx    $acc3, $t0, $acc3
1306         adc     $t0, $acc2
1307         adc     \$0, $acc3
1308
1309         xor     $t3, $t3
1310         add     $acc0, $acc4            # accumulate upper half
1311          mov    .Lpoly+8*1(%rip), $a_ptr
1312         adc     $acc1, $acc5
1313          mov    $acc4, $acc0
1314         adc     $acc2, $acc6
1315         adc     $acc3, $acc7
1316          mov    $acc5, $acc1
1317         adc     \$0, $t3
1318
1319         sub     \$-1, $acc4             # .Lpoly[0]
1320          mov    $acc6, $acc2
1321         sbb     $a_ptr, $acc5           # .Lpoly[1]
1322         sbb     \$0, $acc6              # .Lpoly[2]
1323          mov    $acc7, $acc3
1324         sbb     $t1, $acc7              # .Lpoly[3]
1325         sbb     \$0, $t3
1326
1327         cmovc   $acc0, $acc4
1328         cmovc   $acc1, $acc5
1329         mov     $acc4, 8*0($r_ptr)
1330         cmovc   $acc2, $acc6
1331         mov     $acc5, 8*1($r_ptr)
1332         cmovc   $acc3, $acc7
1333         mov     $acc6, 8*2($r_ptr)
1334         mov     $acc7, 8*3($r_ptr)
1335
1336         ret
1337 .size   __ecp_nistz256_sqr_montx,.-__ecp_nistz256_sqr_montx
1338 ___
1339 }
1340 }
1341 {
1342 my ($r_ptr,$in_ptr)=("%rdi","%rsi");
1343 my ($acc0,$acc1,$acc2,$acc3)=map("%r$_",(8..11));
1344 my ($t0,$t1,$t2)=("%rcx","%r12","%r13");
1345
1346 $code.=<<___;
1347 ################################################################################
1348 # void ecp_nistz256_from_mont(
1349 #   uint64_t res[4],
1350 #   uint64_t in[4]);
1351 # This one performs Montgomery multiplication by 1, so we only need the reduction
1352
1353 .globl  ecp_nistz256_from_mont
1354 .type   ecp_nistz256_from_mont,\@function,2
1355 .align  32
1356 ecp_nistz256_from_mont:
1357 .cfi_startproc
1358         push    %r12
1359 .cfi_push       %r12
1360         push    %r13
1361 .cfi_push       %r13
1362 .Lfrom_body:
1363
1364         mov     8*0($in_ptr), %rax
1365         mov     .Lpoly+8*3(%rip), $t2
1366         mov     8*1($in_ptr), $acc1
1367         mov     8*2($in_ptr), $acc2
1368         mov     8*3($in_ptr), $acc3
1369         mov     %rax, $acc0
1370         mov     .Lpoly+8*1(%rip), $t1
1371
1372         #########################################
1373         # First iteration
1374         mov     %rax, $t0
1375         shl     \$32, $acc0
1376         mulq    $t2
1377         shr     \$32, $t0
1378         add     $acc0, $acc1
1379         adc     $t0, $acc2
1380         adc     %rax, $acc3
1381          mov    $acc1, %rax
1382         adc     \$0, %rdx
1383
1384         #########################################
1385         # Second iteration
1386         mov     $acc1, $t0
1387         shl     \$32, $acc1
1388         mov     %rdx, $acc0
1389         mulq    $t2
1390         shr     \$32, $t0
1391         add     $acc1, $acc2
1392         adc     $t0, $acc3
1393         adc     %rax, $acc0
1394          mov    $acc2, %rax
1395         adc     \$0, %rdx
1396
1397         ##########################################
1398         # Third iteration
1399         mov     $acc2, $t0
1400         shl     \$32, $acc2
1401         mov     %rdx, $acc1
1402         mulq    $t2
1403         shr     \$32, $t0
1404         add     $acc2, $acc3
1405         adc     $t0, $acc0
1406         adc     %rax, $acc1
1407          mov    $acc3, %rax
1408         adc     \$0, %rdx
1409
1410         ###########################################
1411         # Last iteration
1412         mov     $acc3, $t0
1413         shl     \$32, $acc3
1414         mov     %rdx, $acc2
1415         mulq    $t2
1416         shr     \$32, $t0
1417         add     $acc3, $acc0
1418         adc     $t0, $acc1
1419          mov    $acc0, $t0
1420         adc     %rax, $acc2
1421          mov    $acc1, $in_ptr
1422         adc     \$0, %rdx
1423
1424         ###########################################
1425         # Branch-less conditional subtraction
1426         sub     \$-1, $acc0
1427          mov    $acc2, %rax
1428         sbb     $t1, $acc1
1429         sbb     \$0, $acc2
1430          mov    %rdx, $acc3
1431         sbb     $t2, %rdx
1432         sbb     $t2, $t2
1433
1434         cmovnz  $t0, $acc0
1435         cmovnz  $in_ptr, $acc1
1436         mov     $acc0, 8*0($r_ptr)
1437         cmovnz  %rax, $acc2
1438         mov     $acc1, 8*1($r_ptr)
1439         cmovz   %rdx, $acc3
1440         mov     $acc2, 8*2($r_ptr)
1441         mov     $acc3, 8*3($r_ptr)
1442
1443         mov     0(%rsp),%r13
1444 .cfi_restore    %r13
1445         mov     8(%rsp),%r12
1446 .cfi_restore    %r12
1447         lea     16(%rsp),%rsp
1448 .cfi_adjust_cfa_offset  -16
1449 .Lfrom_epilogue:
1450         ret
1451 .cfi_endproc
1452 .size   ecp_nistz256_from_mont,.-ecp_nistz256_from_mont
1453 ___
1454 }
1455 {
1456 my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx");
1457 my ($ONE,$INDEX,$Ra,$Rb,$Rc,$Rd,$Re,$Rf)=map("%xmm$_",(0..7));
1458 my ($M0,$T0a,$T0b,$T0c,$T0d,$T0e,$T0f,$TMP0)=map("%xmm$_",(8..15));
1459 my ($M1,$T2a,$T2b,$TMP2,$M2,$T2a,$T2b,$TMP2)=map("%xmm$_",(8..15));
1460
1461 $code.=<<___;
1462 ################################################################################
1463 # void ecp_nistz256_scatter_w5(uint64_t *val, uint64_t *in_t, int index);
1464 .globl  ecp_nistz256_scatter_w5
1465 .type   ecp_nistz256_scatter_w5,\@abi-omnipotent
1466 .align  32
1467 ecp_nistz256_scatter_w5:
1468         lea     -3($index,$index,2), $index
1469         movdqa  0x00($in_t), %xmm0
1470         shl     \$5, $index
1471         movdqa  0x10($in_t), %xmm1
1472         movdqa  0x20($in_t), %xmm2
1473         movdqa  0x30($in_t), %xmm3
1474         movdqa  0x40($in_t), %xmm4
1475         movdqa  0x50($in_t), %xmm5
1476         movdqa  %xmm0, 0x00($val,$index)
1477         movdqa  %xmm1, 0x10($val,$index)
1478         movdqa  %xmm2, 0x20($val,$index)
1479         movdqa  %xmm3, 0x30($val,$index)
1480         movdqa  %xmm4, 0x40($val,$index)
1481         movdqa  %xmm5, 0x50($val,$index)
1482
1483         ret
1484 .size   ecp_nistz256_scatter_w5,.-ecp_nistz256_scatter_w5
1485
1486 ################################################################################
1487 # void ecp_nistz256_gather_w5(uint64_t *val, uint64_t *in_t, int index);
1488 .globl  ecp_nistz256_gather_w5
1489 .type   ecp_nistz256_gather_w5,\@abi-omnipotent
1490 .align  32
1491 ecp_nistz256_gather_w5:
1492 ___
1493 $code.=<<___    if ($avx>1);
1494         mov     OPENSSL_ia32cap_P+8(%rip), %eax
1495         test    \$`1<<5`, %eax
1496         jnz     .Lavx2_gather_w5
1497 ___
1498 $code.=<<___    if ($win64);
1499         lea     -0x88(%rsp), %rax
1500 .LSEH_begin_ecp_nistz256_gather_w5:
1501         .byte   0x48,0x8d,0x60,0xe0             #lea    -0x20(%rax), %rsp
1502         .byte   0x0f,0x29,0x70,0xe0             #movaps %xmm6, -0x20(%rax)
1503         .byte   0x0f,0x29,0x78,0xf0             #movaps %xmm7, -0x10(%rax)
1504         .byte   0x44,0x0f,0x29,0x00             #movaps %xmm8, 0(%rax)
1505         .byte   0x44,0x0f,0x29,0x48,0x10        #movaps %xmm9, 0x10(%rax)
1506         .byte   0x44,0x0f,0x29,0x50,0x20        #movaps %xmm10, 0x20(%rax)
1507         .byte   0x44,0x0f,0x29,0x58,0x30        #movaps %xmm11, 0x30(%rax)
1508         .byte   0x44,0x0f,0x29,0x60,0x40        #movaps %xmm12, 0x40(%rax)
1509         .byte   0x44,0x0f,0x29,0x68,0x50        #movaps %xmm13, 0x50(%rax)
1510         .byte   0x44,0x0f,0x29,0x70,0x60        #movaps %xmm14, 0x60(%rax)
1511         .byte   0x44,0x0f,0x29,0x78,0x70        #movaps %xmm15, 0x70(%rax)
1512 ___
1513 $code.=<<___;
1514         movdqa  .LOne(%rip), $ONE
1515         movd    $index, $INDEX
1516
1517         pxor    $Ra, $Ra
1518         pxor    $Rb, $Rb
1519         pxor    $Rc, $Rc
1520         pxor    $Rd, $Rd
1521         pxor    $Re, $Re
1522         pxor    $Rf, $Rf
1523
1524         movdqa  $ONE, $M0
1525         pshufd  \$0, $INDEX, $INDEX
1526
1527         mov     \$16, %rax
1528 .Lselect_loop_sse_w5:
1529
1530         movdqa  $M0, $TMP0
1531         paddd   $ONE, $M0
1532         pcmpeqd $INDEX, $TMP0
1533
1534         movdqa  16*0($in_t), $T0a
1535         movdqa  16*1($in_t), $T0b
1536         movdqa  16*2($in_t), $T0c
1537         movdqa  16*3($in_t), $T0d
1538         movdqa  16*4($in_t), $T0e
1539         movdqa  16*5($in_t), $T0f
1540         lea 16*6($in_t), $in_t
1541
1542         pand    $TMP0, $T0a
1543         pand    $TMP0, $T0b
1544         por     $T0a, $Ra
1545         pand    $TMP0, $T0c
1546         por     $T0b, $Rb
1547         pand    $TMP0, $T0d
1548         por     $T0c, $Rc
1549         pand    $TMP0, $T0e
1550         por     $T0d, $Rd
1551         pand    $TMP0, $T0f
1552         por     $T0e, $Re
1553         por     $T0f, $Rf
1554
1555         dec     %rax
1556         jnz     .Lselect_loop_sse_w5
1557
1558         movdqu  $Ra, 16*0($val)
1559         movdqu  $Rb, 16*1($val)
1560         movdqu  $Rc, 16*2($val)
1561         movdqu  $Rd, 16*3($val)
1562         movdqu  $Re, 16*4($val)
1563         movdqu  $Rf, 16*5($val)
1564 ___
1565 $code.=<<___    if ($win64);
1566         movaps  (%rsp), %xmm6
1567         movaps  0x10(%rsp), %xmm7
1568         movaps  0x20(%rsp), %xmm8
1569         movaps  0x30(%rsp), %xmm9
1570         movaps  0x40(%rsp), %xmm10
1571         movaps  0x50(%rsp), %xmm11
1572         movaps  0x60(%rsp), %xmm12
1573         movaps  0x70(%rsp), %xmm13
1574         movaps  0x80(%rsp), %xmm14
1575         movaps  0x90(%rsp), %xmm15
1576         lea     0xa8(%rsp), %rsp
1577 ___
1578 $code.=<<___;
1579         ret
1580 .LSEH_end_ecp_nistz256_gather_w5:
1581 .size   ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5
1582
1583 ################################################################################
1584 # void ecp_nistz256_scatter_w7(uint64_t *val, uint64_t *in_t, int index);
1585 .globl  ecp_nistz256_scatter_w7
1586 .type   ecp_nistz256_scatter_w7,\@abi-omnipotent
1587 .align  32
1588 ecp_nistz256_scatter_w7:
1589         movdqu  0x00($in_t), %xmm0
1590         shl     \$6, $index
1591         movdqu  0x10($in_t), %xmm1
1592         movdqu  0x20($in_t), %xmm2
1593         movdqu  0x30($in_t), %xmm3
1594         movdqa  %xmm0, 0x00($val,$index)
1595         movdqa  %xmm1, 0x10($val,$index)
1596         movdqa  %xmm2, 0x20($val,$index)
1597         movdqa  %xmm3, 0x30($val,$index)
1598
1599         ret
1600 .size   ecp_nistz256_scatter_w7,.-ecp_nistz256_scatter_w7
1601
1602 ################################################################################
1603 # void ecp_nistz256_gather_w7(uint64_t *val, uint64_t *in_t, int index);
1604 .globl  ecp_nistz256_gather_w7
1605 .type   ecp_nistz256_gather_w7,\@abi-omnipotent
1606 .align  32
1607 ecp_nistz256_gather_w7:
1608 ___
1609 $code.=<<___    if ($avx>1);
1610         mov     OPENSSL_ia32cap_P+8(%rip), %eax
1611         test    \$`1<<5`, %eax
1612         jnz     .Lavx2_gather_w7
1613 ___
1614 $code.=<<___    if ($win64);
1615         lea     -0x88(%rsp), %rax
1616 .LSEH_begin_ecp_nistz256_gather_w7:
1617         .byte   0x48,0x8d,0x60,0xe0             #lea    -0x20(%rax), %rsp
1618         .byte   0x0f,0x29,0x70,0xe0             #movaps %xmm6, -0x20(%rax)
1619         .byte   0x0f,0x29,0x78,0xf0             #movaps %xmm7, -0x10(%rax)
1620         .byte   0x44,0x0f,0x29,0x00             #movaps %xmm8, 0(%rax)
1621         .byte   0x44,0x0f,0x29,0x48,0x10        #movaps %xmm9, 0x10(%rax)
1622         .byte   0x44,0x0f,0x29,0x50,0x20        #movaps %xmm10, 0x20(%rax)
1623         .byte   0x44,0x0f,0x29,0x58,0x30        #movaps %xmm11, 0x30(%rax)
1624         .byte   0x44,0x0f,0x29,0x60,0x40        #movaps %xmm12, 0x40(%rax)
1625         .byte   0x44,0x0f,0x29,0x68,0x50        #movaps %xmm13, 0x50(%rax)
1626         .byte   0x44,0x0f,0x29,0x70,0x60        #movaps %xmm14, 0x60(%rax)
1627         .byte   0x44,0x0f,0x29,0x78,0x70        #movaps %xmm15, 0x70(%rax)
1628 ___
1629 $code.=<<___;
1630         movdqa  .LOne(%rip), $M0
1631         movd    $index, $INDEX
1632
1633         pxor    $Ra, $Ra
1634         pxor    $Rb, $Rb
1635         pxor    $Rc, $Rc
1636         pxor    $Rd, $Rd
1637
1638         movdqa  $M0, $ONE
1639         pshufd  \$0, $INDEX, $INDEX
1640         mov     \$64, %rax
1641
1642 .Lselect_loop_sse_w7:
1643         movdqa  $M0, $TMP0
1644         paddd   $ONE, $M0
1645         movdqa  16*0($in_t), $T0a
1646         movdqa  16*1($in_t), $T0b
1647         pcmpeqd $INDEX, $TMP0
1648         movdqa  16*2($in_t), $T0c
1649         movdqa  16*3($in_t), $T0d
1650         lea     16*4($in_t), $in_t
1651
1652         pand    $TMP0, $T0a
1653         pand    $TMP0, $T0b
1654         por     $T0a, $Ra
1655         pand    $TMP0, $T0c
1656         por     $T0b, $Rb
1657         pand    $TMP0, $T0d
1658         por     $T0c, $Rc
1659         prefetcht0      255($in_t)
1660         por     $T0d, $Rd
1661
1662         dec     %rax
1663         jnz     .Lselect_loop_sse_w7
1664
1665         movdqu  $Ra, 16*0($val)
1666         movdqu  $Rb, 16*1($val)
1667         movdqu  $Rc, 16*2($val)
1668         movdqu  $Rd, 16*3($val)
1669 ___
1670 $code.=<<___    if ($win64);
1671         movaps  (%rsp), %xmm6
1672         movaps  0x10(%rsp), %xmm7
1673         movaps  0x20(%rsp), %xmm8
1674         movaps  0x30(%rsp), %xmm9
1675         movaps  0x40(%rsp), %xmm10
1676         movaps  0x50(%rsp), %xmm11
1677         movaps  0x60(%rsp), %xmm12
1678         movaps  0x70(%rsp), %xmm13
1679         movaps  0x80(%rsp), %xmm14
1680         movaps  0x90(%rsp), %xmm15
1681         lea     0xa8(%rsp), %rsp
1682 ___
1683 $code.=<<___;
1684         ret
1685 .LSEH_end_ecp_nistz256_gather_w7:
1686 .size   ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7
1687 ___
1688 }
1689 if ($avx>1) {
1690 my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx");
1691 my ($TWO,$INDEX,$Ra,$Rb,$Rc)=map("%ymm$_",(0..4));
1692 my ($M0,$T0a,$T0b,$T0c,$TMP0)=map("%ymm$_",(5..9));
1693 my ($M1,$T1a,$T1b,$T1c,$TMP1)=map("%ymm$_",(10..14));
1694
1695 $code.=<<___;
1696 ################################################################################
1697 # void ecp_nistz256_avx2_gather_w5(uint64_t *val, uint64_t *in_t, int index);
1698 .type   ecp_nistz256_avx2_gather_w5,\@abi-omnipotent
1699 .align  32
1700 ecp_nistz256_avx2_gather_w5:
1701 .Lavx2_gather_w5:
1702         vzeroupper
1703 ___
1704 $code.=<<___    if ($win64);
1705         lea     -0x88(%rsp), %rax
1706         mov     %rsp,%r11
1707 .LSEH_begin_ecp_nistz256_avx2_gather_w5:
1708         .byte   0x48,0x8d,0x60,0xe0             # lea   -0x20(%rax), %rsp
1709         .byte   0xc5,0xf8,0x29,0x70,0xe0        # vmovaps %xmm6, -0x20(%rax)
1710         .byte   0xc5,0xf8,0x29,0x78,0xf0        # vmovaps %xmm7, -0x10(%rax)
1711         .byte   0xc5,0x78,0x29,0x40,0x00        # vmovaps %xmm8, 8(%rax)
1712         .byte   0xc5,0x78,0x29,0x48,0x10        # vmovaps %xmm9, 0x10(%rax)
1713         .byte   0xc5,0x78,0x29,0x50,0x20        # vmovaps %xmm10, 0x20(%rax)
1714         .byte   0xc5,0x78,0x29,0x58,0x30        # vmovaps %xmm11, 0x30(%rax)
1715         .byte   0xc5,0x78,0x29,0x60,0x40        # vmovaps %xmm12, 0x40(%rax)
1716         .byte   0xc5,0x78,0x29,0x68,0x50        # vmovaps %xmm13, 0x50(%rax)
1717         .byte   0xc5,0x78,0x29,0x70,0x60        # vmovaps %xmm14, 0x60(%rax)
1718         .byte   0xc5,0x78,0x29,0x78,0x70        # vmovaps %xmm15, 0x70(%rax)
1719 ___
1720 $code.=<<___;
1721         vmovdqa .LTwo(%rip), $TWO
1722
1723         vpxor   $Ra, $Ra, $Ra
1724         vpxor   $Rb, $Rb, $Rb
1725         vpxor   $Rc, $Rc, $Rc
1726
1727         vmovdqa .LOne(%rip), $M0
1728         vmovdqa .LTwo(%rip), $M1
1729
1730         vmovd   $index, %xmm1
1731         vpermd  $INDEX, $Ra, $INDEX
1732
1733         mov     \$8, %rax
1734 .Lselect_loop_avx2_w5:
1735
1736         vmovdqa 32*0($in_t), $T0a
1737         vmovdqa 32*1($in_t), $T0b
1738         vmovdqa 32*2($in_t), $T0c
1739
1740         vmovdqa 32*3($in_t), $T1a
1741         vmovdqa 32*4($in_t), $T1b
1742         vmovdqa 32*5($in_t), $T1c
1743
1744         vpcmpeqd        $INDEX, $M0, $TMP0
1745         vpcmpeqd        $INDEX, $M1, $TMP1
1746
1747         vpaddd  $TWO, $M0, $M0
1748         vpaddd  $TWO, $M1, $M1
1749         lea     32*6($in_t), $in_t
1750
1751         vpand   $TMP0, $T0a, $T0a
1752         vpand   $TMP0, $T0b, $T0b
1753         vpand   $TMP0, $T0c, $T0c
1754         vpand   $TMP1, $T1a, $T1a
1755         vpand   $TMP1, $T1b, $T1b
1756         vpand   $TMP1, $T1c, $T1c
1757
1758         vpxor   $T0a, $Ra, $Ra
1759         vpxor   $T0b, $Rb, $Rb
1760         vpxor   $T0c, $Rc, $Rc
1761         vpxor   $T1a, $Ra, $Ra
1762         vpxor   $T1b, $Rb, $Rb
1763         vpxor   $T1c, $Rc, $Rc
1764
1765         dec %rax
1766         jnz .Lselect_loop_avx2_w5
1767
1768         vmovdqu $Ra, 32*0($val)
1769         vmovdqu $Rb, 32*1($val)
1770         vmovdqu $Rc, 32*2($val)
1771         vzeroupper
1772 ___
1773 $code.=<<___    if ($win64);
1774         movaps  (%rsp), %xmm6
1775         movaps  0x10(%rsp), %xmm7
1776         movaps  0x20(%rsp), %xmm8
1777         movaps  0x30(%rsp), %xmm9
1778         movaps  0x40(%rsp), %xmm10
1779         movaps  0x50(%rsp), %xmm11
1780         movaps  0x60(%rsp), %xmm12
1781         movaps  0x70(%rsp), %xmm13
1782         movaps  0x80(%rsp), %xmm14
1783         movaps  0x90(%rsp), %xmm15
1784         lea     (%r11), %rsp
1785 ___
1786 $code.=<<___;
1787         ret
1788 .LSEH_end_ecp_nistz256_avx2_gather_w5:
1789 .size   ecp_nistz256_avx2_gather_w5,.-ecp_nistz256_avx2_gather_w5
1790 ___
1791 }
1792 if ($avx>1) {
1793 my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx");
1794 my ($THREE,$INDEX,$Ra,$Rb)=map("%ymm$_",(0..3));
1795 my ($M0,$T0a,$T0b,$TMP0)=map("%ymm$_",(4..7));
1796 my ($M1,$T1a,$T1b,$TMP1)=map("%ymm$_",(8..11));
1797 my ($M2,$T2a,$T2b,$TMP2)=map("%ymm$_",(12..15));
1798
1799 $code.=<<___;
1800
1801 ################################################################################
1802 # void ecp_nistz256_avx2_gather_w7(uint64_t *val, uint64_t *in_t, int index);
1803 .globl  ecp_nistz256_avx2_gather_w7
1804 .type   ecp_nistz256_avx2_gather_w7,\@abi-omnipotent
1805 .align  32
1806 ecp_nistz256_avx2_gather_w7:
1807 .Lavx2_gather_w7:
1808         vzeroupper
1809 ___
1810 $code.=<<___    if ($win64);
1811         mov     %rsp,%r11
1812         lea     -0x88(%rsp), %rax
1813 .LSEH_begin_ecp_nistz256_avx2_gather_w7:
1814         .byte   0x48,0x8d,0x60,0xe0             # lea   -0x20(%rax), %rsp
1815         .byte   0xc5,0xf8,0x29,0x70,0xe0        # vmovaps %xmm6, -0x20(%rax)
1816         .byte   0xc5,0xf8,0x29,0x78,0xf0        # vmovaps %xmm7, -0x10(%rax)
1817         .byte   0xc5,0x78,0x29,0x40,0x00        # vmovaps %xmm8, 8(%rax)
1818         .byte   0xc5,0x78,0x29,0x48,0x10        # vmovaps %xmm9, 0x10(%rax)
1819         .byte   0xc5,0x78,0x29,0x50,0x20        # vmovaps %xmm10, 0x20(%rax)
1820         .byte   0xc5,0x78,0x29,0x58,0x30        # vmovaps %xmm11, 0x30(%rax)
1821         .byte   0xc5,0x78,0x29,0x60,0x40        # vmovaps %xmm12, 0x40(%rax)
1822         .byte   0xc5,0x78,0x29,0x68,0x50        # vmovaps %xmm13, 0x50(%rax)
1823         .byte   0xc5,0x78,0x29,0x70,0x60        # vmovaps %xmm14, 0x60(%rax)
1824         .byte   0xc5,0x78,0x29,0x78,0x70        # vmovaps %xmm15, 0x70(%rax)
1825 ___
1826 $code.=<<___;
1827         vmovdqa .LThree(%rip), $THREE
1828
1829         vpxor   $Ra, $Ra, $Ra
1830         vpxor   $Rb, $Rb, $Rb
1831
1832         vmovdqa .LOne(%rip), $M0
1833         vmovdqa .LTwo(%rip), $M1
1834         vmovdqa .LThree(%rip), $M2
1835
1836         vmovd   $index, %xmm1
1837         vpermd  $INDEX, $Ra, $INDEX
1838         # Skip index = 0, because it is implicitly the point at infinity
1839
1840         mov     \$21, %rax
1841 .Lselect_loop_avx2_w7:
1842
1843         vmovdqa 32*0($in_t), $T0a
1844         vmovdqa 32*1($in_t), $T0b
1845
1846         vmovdqa 32*2($in_t), $T1a
1847         vmovdqa 32*3($in_t), $T1b
1848
1849         vmovdqa 32*4($in_t), $T2a
1850         vmovdqa 32*5($in_t), $T2b
1851
1852         vpcmpeqd        $INDEX, $M0, $TMP0
1853         vpcmpeqd        $INDEX, $M1, $TMP1
1854         vpcmpeqd        $INDEX, $M2, $TMP2
1855
1856         vpaddd  $THREE, $M0, $M0
1857         vpaddd  $THREE, $M1, $M1
1858         vpaddd  $THREE, $M2, $M2
1859         lea     32*6($in_t), $in_t
1860
1861         vpand   $TMP0, $T0a, $T0a
1862         vpand   $TMP0, $T0b, $T0b
1863         vpand   $TMP1, $T1a, $T1a
1864         vpand   $TMP1, $T1b, $T1b
1865         vpand   $TMP2, $T2a, $T2a
1866         vpand   $TMP2, $T2b, $T2b
1867
1868         vpxor   $T0a, $Ra, $Ra
1869         vpxor   $T0b, $Rb, $Rb
1870         vpxor   $T1a, $Ra, $Ra
1871         vpxor   $T1b, $Rb, $Rb
1872         vpxor   $T2a, $Ra, $Ra
1873         vpxor   $T2b, $Rb, $Rb
1874
1875         dec %rax
1876         jnz .Lselect_loop_avx2_w7
1877
1878
1879         vmovdqa 32*0($in_t), $T0a
1880         vmovdqa 32*1($in_t), $T0b
1881
1882         vpcmpeqd        $INDEX, $M0, $TMP0
1883
1884         vpand   $TMP0, $T0a, $T0a
1885         vpand   $TMP0, $T0b, $T0b
1886
1887         vpxor   $T0a, $Ra, $Ra
1888         vpxor   $T0b, $Rb, $Rb
1889
1890         vmovdqu $Ra, 32*0($val)
1891         vmovdqu $Rb, 32*1($val)
1892         vzeroupper
1893 ___
1894 $code.=<<___    if ($win64);
1895         movaps  (%rsp), %xmm6
1896         movaps  0x10(%rsp), %xmm7
1897         movaps  0x20(%rsp), %xmm8
1898         movaps  0x30(%rsp), %xmm9
1899         movaps  0x40(%rsp), %xmm10
1900         movaps  0x50(%rsp), %xmm11
1901         movaps  0x60(%rsp), %xmm12
1902         movaps  0x70(%rsp), %xmm13
1903         movaps  0x80(%rsp), %xmm14
1904         movaps  0x90(%rsp), %xmm15
1905         lea     (%r11), %rsp
1906 ___
1907 $code.=<<___;
1908         ret
1909 .LSEH_end_ecp_nistz256_avx2_gather_w7:
1910 .size   ecp_nistz256_avx2_gather_w7,.-ecp_nistz256_avx2_gather_w7
1911 ___
1912 } else {
1913 $code.=<<___;
1914 .globl  ecp_nistz256_avx2_gather_w7
1915 .type   ecp_nistz256_avx2_gather_w7,\@function,3
1916 .align  32
1917 ecp_nistz256_avx2_gather_w7:
1918         .byte   0x0f,0x0b       # ud2
1919         ret
1920 .size   ecp_nistz256_avx2_gather_w7,.-ecp_nistz256_avx2_gather_w7
1921 ___
1922 }
1923 {{{
1924 ########################################################################
1925 # This block implements higher level point_double, point_add and
1926 # point_add_affine. The key to performance in this case is to allow
1927 # out-of-order execution logic to overlap computations from next step
1928 # with tail processing from current step. By using tailored calling
1929 # sequence we minimize inter-step overhead to give processor better
1930 # shot at overlapping operations...
1931 #
1932 # You will notice that input data is copied to stack. Trouble is that
1933 # there are no registers to spare for holding original pointers and
1934 # reloading them, pointers, would create undesired dependencies on
1935 # effective addresses calculation paths. In other words it's too done
1936 # to favour out-of-order execution logic.
1937 #                                               <appro@openssl.org>
1938
1939 my ($r_ptr,$a_ptr,$b_org,$b_ptr)=("%rdi","%rsi","%rdx","%rbx");
1940 my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("%r$_",(8..15));
1941 my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rbp","%rcx",$acc4,$acc4);
1942 my ($poly1,$poly3)=($acc6,$acc7);
1943
1944 sub load_for_mul () {
1945 my ($a,$b,$src0) = @_;
1946 my $bias = $src0 eq "%rax" ? 0 : -128;
1947
1948 "       mov     $b, $src0
1949         lea     $b, $b_ptr
1950         mov     8*0+$a, $acc1
1951         mov     8*1+$a, $acc2
1952         lea     $bias+$a, $a_ptr
1953         mov     8*2+$a, $acc3
1954         mov     8*3+$a, $acc4"
1955 }
1956
1957 sub load_for_sqr () {
1958 my ($a,$src0) = @_;
1959 my $bias = $src0 eq "%rax" ? 0 : -128;
1960
1961 "       mov     8*0+$a, $src0
1962         mov     8*1+$a, $acc6
1963         lea     $bias+$a, $a_ptr
1964         mov     8*2+$a, $acc7
1965         mov     8*3+$a, $acc0"
1966 }
1967
1968                                                                         {
1969 ########################################################################
1970 # operate in 4-5-0-1 "name space" that matches multiplication output
1971 #
1972 my ($a0,$a1,$a2,$a3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3);
1973
1974 $code.=<<___;
1975 .type   __ecp_nistz256_add_toq,\@abi-omnipotent
1976 .align  32
1977 __ecp_nistz256_add_toq:
1978         xor     $t4,$t4
1979         add     8*0($b_ptr), $a0
1980         adc     8*1($b_ptr), $a1
1981          mov    $a0, $t0
1982         adc     8*2($b_ptr), $a2
1983         adc     8*3($b_ptr), $a3
1984          mov    $a1, $t1
1985         adc     \$0, $t4
1986
1987         sub     \$-1, $a0
1988          mov    $a2, $t2
1989         sbb     $poly1, $a1
1990         sbb     \$0, $a2
1991          mov    $a3, $t3
1992         sbb     $poly3, $a3
1993         sbb     \$0, $t4
1994
1995         cmovc   $t0, $a0
1996         cmovc   $t1, $a1
1997         mov     $a0, 8*0($r_ptr)
1998         cmovc   $t2, $a2
1999         mov     $a1, 8*1($r_ptr)
2000         cmovc   $t3, $a3
2001         mov     $a2, 8*2($r_ptr)
2002         mov     $a3, 8*3($r_ptr)
2003
2004         ret
2005 .size   __ecp_nistz256_add_toq,.-__ecp_nistz256_add_toq
2006
2007 .type   __ecp_nistz256_sub_fromq,\@abi-omnipotent
2008 .align  32
2009 __ecp_nistz256_sub_fromq:
2010         sub     8*0($b_ptr), $a0
2011         sbb     8*1($b_ptr), $a1
2012          mov    $a0, $t0
2013         sbb     8*2($b_ptr), $a2
2014         sbb     8*3($b_ptr), $a3
2015          mov    $a1, $t1
2016         sbb     $t4, $t4
2017
2018         add     \$-1, $a0
2019          mov    $a2, $t2
2020         adc     $poly1, $a1
2021         adc     \$0, $a2
2022          mov    $a3, $t3
2023         adc     $poly3, $a3
2024         test    $t4, $t4
2025
2026         cmovz   $t0, $a0
2027         cmovz   $t1, $a1
2028         mov     $a0, 8*0($r_ptr)
2029         cmovz   $t2, $a2
2030         mov     $a1, 8*1($r_ptr)
2031         cmovz   $t3, $a3
2032         mov     $a2, 8*2($r_ptr)
2033         mov     $a3, 8*3($r_ptr)
2034
2035         ret
2036 .size   __ecp_nistz256_sub_fromq,.-__ecp_nistz256_sub_fromq
2037
2038 .type   __ecp_nistz256_subq,\@abi-omnipotent
2039 .align  32
2040 __ecp_nistz256_subq:
2041         sub     $a0, $t0
2042         sbb     $a1, $t1
2043          mov    $t0, $a0
2044         sbb     $a2, $t2
2045         sbb     $a3, $t3
2046          mov    $t1, $a1
2047         sbb     $t4, $t4
2048
2049         add     \$-1, $t0
2050          mov    $t2, $a2
2051         adc     $poly1, $t1
2052         adc     \$0, $t2
2053          mov    $t3, $a3
2054         adc     $poly3, $t3
2055         test    $t4, $t4
2056
2057         cmovnz  $t0, $a0
2058         cmovnz  $t1, $a1
2059         cmovnz  $t2, $a2
2060         cmovnz  $t3, $a3
2061
2062         ret
2063 .size   __ecp_nistz256_subq,.-__ecp_nistz256_subq
2064
2065 .type   __ecp_nistz256_mul_by_2q,\@abi-omnipotent
2066 .align  32
2067 __ecp_nistz256_mul_by_2q:
2068         xor     $t4, $t4
2069         add     $a0, $a0                # a0:a3+a0:a3
2070         adc     $a1, $a1
2071          mov    $a0, $t0
2072         adc     $a2, $a2
2073         adc     $a3, $a3
2074          mov    $a1, $t1
2075         adc     \$0, $t4
2076
2077         sub     \$-1, $a0
2078          mov    $a2, $t2
2079         sbb     $poly1, $a1
2080         sbb     \$0, $a2
2081          mov    $a3, $t3
2082         sbb     $poly3, $a3
2083         sbb     \$0, $t4
2084
2085         cmovc   $t0, $a0
2086         cmovc   $t1, $a1
2087         mov     $a0, 8*0($r_ptr)
2088         cmovc   $t2, $a2
2089         mov     $a1, 8*1($r_ptr)
2090         cmovc   $t3, $a3
2091         mov     $a2, 8*2($r_ptr)
2092         mov     $a3, 8*3($r_ptr)
2093
2094         ret
2095 .size   __ecp_nistz256_mul_by_2q,.-__ecp_nistz256_mul_by_2q
2096 ___
2097                                                                         }
2098 sub gen_double () {
2099     my $x = shift;
2100     my ($src0,$sfx,$bias);
2101     my ($S,$M,$Zsqr,$in_x,$tmp0)=map(32*$_,(0..4));
2102
2103     if ($x ne "x") {
2104         $src0 = "%rax";
2105         $sfx  = "";
2106         $bias = 0;
2107
2108 $code.=<<___;
2109 .globl  ecp_nistz256_point_double
2110 .type   ecp_nistz256_point_double,\@function,2
2111 .align  32
2112 ecp_nistz256_point_double:
2113 .cfi_startproc
2114 ___
2115 $code.=<<___    if ($addx);
2116         mov     \$0x80100, %ecx
2117         and     OPENSSL_ia32cap_P+8(%rip), %ecx
2118         cmp     \$0x80100, %ecx
2119         je      .Lpoint_doublex
2120 ___
2121     } else {
2122         $src0 = "%rdx";
2123         $sfx  = "x";
2124         $bias = 128;
2125
2126 $code.=<<___;
2127 .type   ecp_nistz256_point_doublex,\@function,2
2128 .align  32
2129 ecp_nistz256_point_doublex:
2130 .cfi_startproc
2131 .Lpoint_doublex:
2132 ___
2133     }
2134 $code.=<<___;
2135         push    %rbp
2136 .cfi_push       %rbp
2137         push    %rbx
2138 .cfi_push       %rbx
2139         push    %r12
2140 .cfi_push       %r12
2141         push    %r13
2142 .cfi_push       %r13
2143         push    %r14
2144 .cfi_push       %r14
2145         push    %r15
2146 .cfi_push       %r15
2147         sub     \$32*5+8, %rsp
2148 .cfi_adjust_cfa_offset  32*5+8
2149 .Lpoint_double${x}_body:
2150
2151 .Lpoint_double_shortcut$x:
2152         movdqu  0x00($a_ptr), %xmm0             # copy  *(P256_POINT *)$a_ptr.x
2153         mov     $a_ptr, $b_ptr                  # backup copy
2154         movdqu  0x10($a_ptr), %xmm1
2155          mov    0x20+8*0($a_ptr), $acc4         # load in_y in "5-4-0-1" order
2156          mov    0x20+8*1($a_ptr), $acc5
2157          mov    0x20+8*2($a_ptr), $acc0
2158          mov    0x20+8*3($a_ptr), $acc1
2159          mov    .Lpoly+8*1(%rip), $poly1
2160          mov    .Lpoly+8*3(%rip), $poly3
2161         movdqa  %xmm0, $in_x(%rsp)
2162         movdqa  %xmm1, $in_x+0x10(%rsp)
2163         lea     0x20($r_ptr), $acc2
2164         lea     0x40($r_ptr), $acc3
2165         movq    $r_ptr, %xmm0
2166         movq    $acc2, %xmm1
2167         movq    $acc3, %xmm2
2168
2169         lea     $S(%rsp), $r_ptr
2170         call    __ecp_nistz256_mul_by_2$x       # p256_mul_by_2(S, in_y);
2171
2172         mov     0x40+8*0($a_ptr), $src0
2173         mov     0x40+8*1($a_ptr), $acc6
2174         mov     0x40+8*2($a_ptr), $acc7
2175         mov     0x40+8*3($a_ptr), $acc0
2176         lea     0x40-$bias($a_ptr), $a_ptr
2177         lea     $Zsqr(%rsp), $r_ptr
2178         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(Zsqr, in_z);
2179
2180         `&load_for_sqr("$S(%rsp)", "$src0")`
2181         lea     $S(%rsp), $r_ptr
2182         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(S, S);
2183
2184         mov     0x20($b_ptr), $src0             # $b_ptr is still valid
2185         mov     0x40+8*0($b_ptr), $acc1
2186         mov     0x40+8*1($b_ptr), $acc2
2187         mov     0x40+8*2($b_ptr), $acc3
2188         mov     0x40+8*3($b_ptr), $acc4
2189         lea     0x40-$bias($b_ptr), $a_ptr
2190         lea     0x20($b_ptr), $b_ptr
2191         movq    %xmm2, $r_ptr
2192         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(res_z, in_z, in_y);
2193         call    __ecp_nistz256_mul_by_2$x       # p256_mul_by_2(res_z, res_z);
2194
2195         mov     $in_x+8*0(%rsp), $acc4          # "5-4-0-1" order
2196         mov     $in_x+8*1(%rsp), $acc5
2197         lea     $Zsqr(%rsp), $b_ptr
2198         mov     $in_x+8*2(%rsp), $acc0
2199         mov     $in_x+8*3(%rsp), $acc1
2200         lea     $M(%rsp), $r_ptr
2201         call    __ecp_nistz256_add_to$x         # p256_add(M, in_x, Zsqr);
2202
2203         mov     $in_x+8*0(%rsp), $acc4          # "5-4-0-1" order
2204         mov     $in_x+8*1(%rsp), $acc5
2205         lea     $Zsqr(%rsp), $b_ptr
2206         mov     $in_x+8*2(%rsp), $acc0
2207         mov     $in_x+8*3(%rsp), $acc1
2208         lea     $Zsqr(%rsp), $r_ptr
2209         call    __ecp_nistz256_sub_from$x       # p256_sub(Zsqr, in_x, Zsqr);
2210
2211         `&load_for_sqr("$S(%rsp)", "$src0")`
2212         movq    %xmm1, $r_ptr
2213         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(res_y, S);
2214 ___
2215 {
2216 ######## ecp_nistz256_div_by_2(res_y, res_y); ##########################
2217 # operate in 4-5-6-7 "name space" that matches squaring output
2218 #
2219 my ($poly1,$poly3)=($a_ptr,$t1);
2220 my ($a0,$a1,$a2,$a3,$t3,$t4,$t1)=($acc4,$acc5,$acc6,$acc7,$acc0,$acc1,$acc2);
2221
2222 $code.=<<___;
2223         xor     $t4, $t4
2224         mov     $a0, $t0
2225         add     \$-1, $a0
2226         mov     $a1, $t1
2227         adc     $poly1, $a1
2228         mov     $a2, $t2
2229         adc     \$0, $a2
2230         mov     $a3, $t3
2231         adc     $poly3, $a3
2232         adc     \$0, $t4
2233         xor     $a_ptr, $a_ptr          # borrow $a_ptr
2234         test    \$1, $t0
2235
2236         cmovz   $t0, $a0
2237         cmovz   $t1, $a1
2238         cmovz   $t2, $a2
2239         cmovz   $t3, $a3
2240         cmovz   $a_ptr, $t4
2241
2242         mov     $a1, $t0                # a0:a3>>1
2243         shr     \$1, $a0
2244         shl     \$63, $t0
2245         mov     $a2, $t1
2246         shr     \$1, $a1
2247         or      $t0, $a0
2248         shl     \$63, $t1
2249         mov     $a3, $t2
2250         shr     \$1, $a2
2251         or      $t1, $a1
2252         shl     \$63, $t2
2253         mov     $a0, 8*0($r_ptr)
2254         shr     \$1, $a3
2255         mov     $a1, 8*1($r_ptr)
2256         shl     \$63, $t4
2257         or      $t2, $a2
2258         or      $t4, $a3
2259         mov     $a2, 8*2($r_ptr)
2260         mov     $a3, 8*3($r_ptr)
2261 ___
2262 }
2263 $code.=<<___;
2264         `&load_for_mul("$M(%rsp)", "$Zsqr(%rsp)", "$src0")`
2265         lea     $M(%rsp), $r_ptr
2266         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(M, M, Zsqr);
2267
2268         lea     $tmp0(%rsp), $r_ptr
2269         call    __ecp_nistz256_mul_by_2$x
2270
2271         lea     $M(%rsp), $b_ptr
2272         lea     $M(%rsp), $r_ptr
2273         call    __ecp_nistz256_add_to$x         # p256_mul_by_3(M, M);
2274
2275         `&load_for_mul("$S(%rsp)", "$in_x(%rsp)", "$src0")`
2276         lea     $S(%rsp), $r_ptr
2277         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S, S, in_x);
2278
2279         lea     $tmp0(%rsp), $r_ptr
2280         call    __ecp_nistz256_mul_by_2$x       # p256_mul_by_2(tmp0, S);
2281
2282         `&load_for_sqr("$M(%rsp)", "$src0")`
2283         movq    %xmm0, $r_ptr
2284         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(res_x, M);
2285
2286         lea     $tmp0(%rsp), $b_ptr
2287         mov     $acc6, $acc0                    # harmonize sqr output and sub input
2288         mov     $acc7, $acc1
2289         mov     $a_ptr, $poly1
2290         mov     $t1, $poly3
2291         call    __ecp_nistz256_sub_from$x       # p256_sub(res_x, res_x, tmp0);
2292
2293         mov     $S+8*0(%rsp), $t0
2294         mov     $S+8*1(%rsp), $t1
2295         mov     $S+8*2(%rsp), $t2
2296         mov     $S+8*3(%rsp), $acc2             # "4-5-0-1" order
2297         lea     $S(%rsp), $r_ptr
2298         call    __ecp_nistz256_sub$x            # p256_sub(S, S, res_x);
2299
2300         mov     $M(%rsp), $src0
2301         lea     $M(%rsp), $b_ptr
2302         mov     $acc4, $acc6                    # harmonize sub output and mul input
2303         xor     %ecx, %ecx
2304         mov     $acc4, $S+8*0(%rsp)             # have to save:-(
2305         mov     $acc5, $acc2
2306         mov     $acc5, $S+8*1(%rsp)
2307         cmovz   $acc0, $acc3
2308         mov     $acc0, $S+8*2(%rsp)
2309         lea     $S-$bias(%rsp), $a_ptr
2310         cmovz   $acc1, $acc4
2311         mov     $acc1, $S+8*3(%rsp)
2312         mov     $acc6, $acc1
2313         lea     $S(%rsp), $r_ptr
2314         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S, S, M);
2315
2316         movq    %xmm1, $b_ptr
2317         movq    %xmm1, $r_ptr
2318         call    __ecp_nistz256_sub_from$x       # p256_sub(res_y, S, res_y);
2319
2320         lea     32*5+56(%rsp), %rsi
2321 .cfi_def_cfa    %rsi,8
2322         mov     -48(%rsi),%r15
2323 .cfi_restore    %r15
2324         mov     -40(%rsi),%r14
2325 .cfi_restore    %r14
2326         mov     -32(%rsi),%r13
2327 .cfi_restore    %r13
2328         mov     -24(%rsi),%r12
2329 .cfi_restore    %r12
2330         mov     -16(%rsi),%rbx
2331 .cfi_restore    %rbx
2332         mov     -8(%rsi),%rbp
2333 .cfi_restore    %rbp
2334         lea     (%rsi),%rsp
2335 .cfi_def_cfa_register   %rsp
2336 .Lpoint_double${x}_epilogue:
2337         ret
2338 .cfi_endproc
2339 .size   ecp_nistz256_point_double$sfx,.-ecp_nistz256_point_double$sfx
2340 ___
2341 }
2342 &gen_double("q");
2343
2344 sub gen_add () {
2345     my $x = shift;
2346     my ($src0,$sfx,$bias);
2347     my ($H,$Hsqr,$R,$Rsqr,$Hcub,
2348         $U1,$U2,$S1,$S2,
2349         $res_x,$res_y,$res_z,
2350         $in1_x,$in1_y,$in1_z,
2351         $in2_x,$in2_y,$in2_z)=map(32*$_,(0..17));
2352     my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr);
2353
2354     if ($x ne "x") {
2355         $src0 = "%rax";
2356         $sfx  = "";
2357         $bias = 0;
2358
2359 $code.=<<___;
2360 .globl  ecp_nistz256_point_add
2361 .type   ecp_nistz256_point_add,\@function,3
2362 .align  32
2363 ecp_nistz256_point_add:
2364 .cfi_startproc
2365 ___
2366 $code.=<<___    if ($addx);
2367         mov     \$0x80100, %ecx
2368         and     OPENSSL_ia32cap_P+8(%rip), %ecx
2369         cmp     \$0x80100, %ecx
2370         je      .Lpoint_addx
2371 ___
2372     } else {
2373         $src0 = "%rdx";
2374         $sfx  = "x";
2375         $bias = 128;
2376
2377 $code.=<<___;
2378 .type   ecp_nistz256_point_addx,\@function,3
2379 .align  32
2380 ecp_nistz256_point_addx:
2381 .cfi_startproc
2382 .Lpoint_addx:
2383 ___
2384     }
2385 $code.=<<___;
2386         push    %rbp
2387 .cfi_push       %rbp
2388         push    %rbx
2389 .cfi_push       %rbx
2390         push    %r12
2391 .cfi_push       %r12
2392         push    %r13
2393 .cfi_push       %r13
2394         push    %r14
2395 .cfi_push       %r14
2396         push    %r15
2397 .cfi_push       %r15
2398         sub     \$32*18+8, %rsp
2399 .cfi_adjust_cfa_offset  32*18+8
2400 .Lpoint_add${x}_body:
2401
2402         movdqu  0x00($a_ptr), %xmm0             # copy  *(P256_POINT *)$a_ptr
2403         movdqu  0x10($a_ptr), %xmm1
2404         movdqu  0x20($a_ptr), %xmm2
2405         movdqu  0x30($a_ptr), %xmm3
2406         movdqu  0x40($a_ptr), %xmm4
2407         movdqu  0x50($a_ptr), %xmm5
2408         mov     $a_ptr, $b_ptr                  # reassign
2409         mov     $b_org, $a_ptr                  # reassign
2410         movdqa  %xmm0, $in1_x(%rsp)
2411         movdqa  %xmm1, $in1_x+0x10(%rsp)
2412         movdqa  %xmm2, $in1_y(%rsp)
2413         movdqa  %xmm3, $in1_y+0x10(%rsp)
2414         movdqa  %xmm4, $in1_z(%rsp)
2415         movdqa  %xmm5, $in1_z+0x10(%rsp)
2416         por     %xmm4, %xmm5
2417
2418         movdqu  0x00($a_ptr), %xmm0             # copy  *(P256_POINT *)$b_ptr
2419          pshufd \$0xb1, %xmm5, %xmm3
2420         movdqu  0x10($a_ptr), %xmm1
2421         movdqu  0x20($a_ptr), %xmm2
2422          por    %xmm3, %xmm5
2423         movdqu  0x30($a_ptr), %xmm3
2424          mov    0x40+8*0($a_ptr), $src0         # load original in2_z
2425          mov    0x40+8*1($a_ptr), $acc6
2426          mov    0x40+8*2($a_ptr), $acc7
2427          mov    0x40+8*3($a_ptr), $acc0
2428         movdqa  %xmm0, $in2_x(%rsp)
2429          pshufd \$0x1e, %xmm5, %xmm4
2430         movdqa  %xmm1, $in2_x+0x10(%rsp)
2431         movdqu  0x40($a_ptr),%xmm0              # in2_z again
2432         movdqu  0x50($a_ptr),%xmm1
2433         movdqa  %xmm2, $in2_y(%rsp)
2434         movdqa  %xmm3, $in2_y+0x10(%rsp)
2435          por    %xmm4, %xmm5
2436          pxor   %xmm4, %xmm4
2437         por     %xmm0, %xmm1
2438          movq   $r_ptr, %xmm0                   # save $r_ptr
2439
2440         lea     0x40-$bias($a_ptr), $a_ptr      # $a_ptr is still valid
2441          mov    $src0, $in2_z+8*0(%rsp)         # make in2_z copy
2442          mov    $acc6, $in2_z+8*1(%rsp)
2443          mov    $acc7, $in2_z+8*2(%rsp)
2444          mov    $acc0, $in2_z+8*3(%rsp)
2445         lea     $Z2sqr(%rsp), $r_ptr            # Z2^2
2446         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(Z2sqr, in2_z);
2447
2448         pcmpeqd %xmm4, %xmm5
2449         pshufd  \$0xb1, %xmm1, %xmm4
2450         por     %xmm1, %xmm4
2451         pshufd  \$0, %xmm5, %xmm5               # in1infty
2452         pshufd  \$0x1e, %xmm4, %xmm3
2453         por     %xmm3, %xmm4
2454         pxor    %xmm3, %xmm3
2455         pcmpeqd %xmm3, %xmm4
2456         pshufd  \$0, %xmm4, %xmm4               # in2infty
2457          mov    0x40+8*0($b_ptr), $src0         # load original in1_z
2458          mov    0x40+8*1($b_ptr), $acc6
2459          mov    0x40+8*2($b_ptr), $acc7
2460          mov    0x40+8*3($b_ptr), $acc0
2461         movq    $b_ptr, %xmm1
2462
2463         lea     0x40-$bias($b_ptr), $a_ptr
2464         lea     $Z1sqr(%rsp), $r_ptr            # Z1^2
2465         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(Z1sqr, in1_z);
2466
2467         `&load_for_mul("$Z2sqr(%rsp)", "$in2_z(%rsp)", "$src0")`
2468         lea     $S1(%rsp), $r_ptr               # S1 = Z2^3
2469         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S1, Z2sqr, in2_z);
2470
2471         `&load_for_mul("$Z1sqr(%rsp)", "$in1_z(%rsp)", "$src0")`
2472         lea     $S2(%rsp), $r_ptr               # S2 = Z1^3
2473         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S2, Z1sqr, in1_z);
2474
2475         `&load_for_mul("$S1(%rsp)", "$in1_y(%rsp)", "$src0")`
2476         lea     $S1(%rsp), $r_ptr               # S1 = Y1*Z2^3
2477         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S1, S1, in1_y);
2478
2479         `&load_for_mul("$S2(%rsp)", "$in2_y(%rsp)", "$src0")`
2480         lea     $S2(%rsp), $r_ptr               # S2 = Y2*Z1^3
2481         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S2, S2, in2_y);
2482
2483         lea     $S1(%rsp), $b_ptr
2484         lea     $R(%rsp), $r_ptr                # R = S2 - S1
2485         call    __ecp_nistz256_sub_from$x       # p256_sub(R, S2, S1);
2486
2487         or      $acc5, $acc4                    # see if result is zero
2488         movdqa  %xmm4, %xmm2
2489         or      $acc0, $acc4
2490         or      $acc1, $acc4
2491         por     %xmm5, %xmm2                    # in1infty || in2infty
2492         movq    $acc4, %xmm3
2493
2494         `&load_for_mul("$Z2sqr(%rsp)", "$in1_x(%rsp)", "$src0")`
2495         lea     $U1(%rsp), $r_ptr               # U1 = X1*Z2^2
2496         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(U1, in1_x, Z2sqr);
2497
2498         `&load_for_mul("$Z1sqr(%rsp)", "$in2_x(%rsp)", "$src0")`
2499         lea     $U2(%rsp), $r_ptr               # U2 = X2*Z1^2
2500         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(U2, in2_x, Z1sqr);
2501
2502         lea     $U1(%rsp), $b_ptr
2503         lea     $H(%rsp), $r_ptr                # H = U2 - U1
2504         call    __ecp_nistz256_sub_from$x       # p256_sub(H, U2, U1);
2505
2506         or      $acc5, $acc4                    # see if result is zero
2507         or      $acc0, $acc4
2508         or      $acc1, $acc4
2509
2510         .byte   0x3e                            # predict taken
2511         jnz     .Ladd_proceed$x                 # is_equal(U1,U2)?
2512         movq    %xmm2, $acc0
2513         movq    %xmm3, $acc1
2514         test    $acc0, $acc0
2515         jnz     .Ladd_proceed$x                 # (in1infty || in2infty)?
2516         test    $acc1, $acc1
2517         jz      .Ladd_double$x                  # is_equal(S1,S2)?
2518
2519         movq    %xmm0, $r_ptr                   # restore $r_ptr
2520         pxor    %xmm0, %xmm0
2521         movdqu  %xmm0, 0x00($r_ptr)
2522         movdqu  %xmm0, 0x10($r_ptr)
2523         movdqu  %xmm0, 0x20($r_ptr)
2524         movdqu  %xmm0, 0x30($r_ptr)
2525         movdqu  %xmm0, 0x40($r_ptr)
2526         movdqu  %xmm0, 0x50($r_ptr)
2527         jmp     .Ladd_done$x
2528
2529 .align  32
2530 .Ladd_double$x:
2531         movq    %xmm1, $a_ptr                   # restore $a_ptr
2532         movq    %xmm0, $r_ptr                   # restore $r_ptr
2533         add     \$`32*(18-5)`, %rsp             # difference in frame sizes
2534         jmp     .Lpoint_double_shortcut$x
2535
2536 .align  32
2537 .Ladd_proceed$x:
2538         `&load_for_sqr("$R(%rsp)", "$src0")`
2539         lea     $Rsqr(%rsp), $r_ptr             # R^2
2540         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(Rsqr, R);
2541
2542         `&load_for_mul("$H(%rsp)", "$in1_z(%rsp)", "$src0")`
2543         lea     $res_z(%rsp), $r_ptr            # Z3 = H*Z1*Z2
2544         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(res_z, H, in1_z);
2545
2546         `&load_for_sqr("$H(%rsp)", "$src0")`
2547         lea     $Hsqr(%rsp), $r_ptr             # H^2
2548         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(Hsqr, H);
2549
2550         `&load_for_mul("$res_z(%rsp)", "$in2_z(%rsp)", "$src0")`
2551         lea     $res_z(%rsp), $r_ptr            # Z3 = H*Z1*Z2
2552         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(res_z, res_z, in2_z);
2553
2554         `&load_for_mul("$Hsqr(%rsp)", "$H(%rsp)", "$src0")`
2555         lea     $Hcub(%rsp), $r_ptr             # H^3
2556         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(Hcub, Hsqr, H);
2557
2558         `&load_for_mul("$Hsqr(%rsp)", "$U1(%rsp)", "$src0")`
2559         lea     $U2(%rsp), $r_ptr               # U1*H^2
2560         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(U2, U1, Hsqr);
2561 ___
2562 {
2563 #######################################################################
2564 # operate in 4-5-0-1 "name space" that matches multiplication output
2565 #
2566 my ($acc0,$acc1,$acc2,$acc3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3);
2567 my ($poly1, $poly3)=($acc6,$acc7);
2568
2569 $code.=<<___;
2570         #lea    $U2(%rsp), $a_ptr
2571         #lea    $Hsqr(%rsp), $r_ptr     # 2*U1*H^2
2572         #call   __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2);
2573
2574         xor     $t4, $t4
2575         add     $acc0, $acc0            # a0:a3+a0:a3
2576         lea     $Rsqr(%rsp), $a_ptr
2577         adc     $acc1, $acc1
2578          mov    $acc0, $t0
2579         adc     $acc2, $acc2
2580         adc     $acc3, $acc3
2581          mov    $acc1, $t1
2582         adc     \$0, $t4
2583
2584         sub     \$-1, $acc0
2585          mov    $acc2, $t2
2586         sbb     $poly1, $acc1
2587         sbb     \$0, $acc2
2588          mov    $acc3, $t3
2589         sbb     $poly3, $acc3
2590         sbb     \$0, $t4
2591
2592         cmovc   $t0, $acc0
2593         mov     8*0($a_ptr), $t0
2594         cmovc   $t1, $acc1
2595         mov     8*1($a_ptr), $t1
2596         cmovc   $t2, $acc2
2597         mov     8*2($a_ptr), $t2
2598         cmovc   $t3, $acc3
2599         mov     8*3($a_ptr), $t3
2600
2601         call    __ecp_nistz256_sub$x            # p256_sub(res_x, Rsqr, Hsqr);
2602
2603         lea     $Hcub(%rsp), $b_ptr
2604         lea     $res_x(%rsp), $r_ptr
2605         call    __ecp_nistz256_sub_from$x       # p256_sub(res_x, res_x, Hcub);
2606
2607         mov     $U2+8*0(%rsp), $t0
2608         mov     $U2+8*1(%rsp), $t1
2609         mov     $U2+8*2(%rsp), $t2
2610         mov     $U2+8*3(%rsp), $t3
2611         lea     $res_y(%rsp), $r_ptr
2612
2613         call    __ecp_nistz256_sub$x            # p256_sub(res_y, U2, res_x);
2614
2615         mov     $acc0, 8*0($r_ptr)              # save the result, as
2616         mov     $acc1, 8*1($r_ptr)              # __ecp_nistz256_sub doesn't
2617         mov     $acc2, 8*2($r_ptr)
2618         mov     $acc3, 8*3($r_ptr)
2619 ___
2620 }
2621 $code.=<<___;
2622         `&load_for_mul("$S1(%rsp)", "$Hcub(%rsp)", "$src0")`
2623         lea     $S2(%rsp), $r_ptr
2624         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S2, S1, Hcub);
2625
2626         `&load_for_mul("$R(%rsp)", "$res_y(%rsp)", "$src0")`
2627         lea     $res_y(%rsp), $r_ptr
2628         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(res_y, R, res_y);
2629
2630         lea     $S2(%rsp), $b_ptr
2631         lea     $res_y(%rsp), $r_ptr
2632         call    __ecp_nistz256_sub_from$x       # p256_sub(res_y, res_y, S2);
2633
2634         movq    %xmm0, $r_ptr           # restore $r_ptr
2635
2636         movdqa  %xmm5, %xmm0            # copy_conditional(res_z, in2_z, in1infty);
2637         movdqa  %xmm5, %xmm1
2638         pandn   $res_z(%rsp), %xmm0
2639         movdqa  %xmm5, %xmm2
2640         pandn   $res_z+0x10(%rsp), %xmm1
2641         movdqa  %xmm5, %xmm3
2642         pand    $in2_z(%rsp), %xmm2
2643         pand    $in2_z+0x10(%rsp), %xmm3
2644         por     %xmm0, %xmm2
2645         por     %xmm1, %xmm3
2646
2647         movdqa  %xmm4, %xmm0            # copy_conditional(res_z, in1_z, in2infty);
2648         movdqa  %xmm4, %xmm1
2649         pandn   %xmm2, %xmm0
2650         movdqa  %xmm4, %xmm2
2651         pandn   %xmm3, %xmm1
2652         movdqa  %xmm4, %xmm3
2653         pand    $in1_z(%rsp), %xmm2
2654         pand    $in1_z+0x10(%rsp), %xmm3
2655         por     %xmm0, %xmm2
2656         por     %xmm1, %xmm3
2657         movdqu  %xmm2, 0x40($r_ptr)
2658         movdqu  %xmm3, 0x50($r_ptr)
2659
2660         movdqa  %xmm5, %xmm0            # copy_conditional(res_x, in2_x, in1infty);
2661         movdqa  %xmm5, %xmm1
2662         pandn   $res_x(%rsp), %xmm0
2663         movdqa  %xmm5, %xmm2
2664         pandn   $res_x+0x10(%rsp), %xmm1
2665         movdqa  %xmm5, %xmm3
2666         pand    $in2_x(%rsp), %xmm2
2667         pand    $in2_x+0x10(%rsp), %xmm3
2668         por     %xmm0, %xmm2
2669         por     %xmm1, %xmm3
2670
2671         movdqa  %xmm4, %xmm0            # copy_conditional(res_x, in1_x, in2infty);
2672         movdqa  %xmm4, %xmm1
2673         pandn   %xmm2, %xmm0
2674         movdqa  %xmm4, %xmm2
2675         pandn   %xmm3, %xmm1
2676         movdqa  %xmm4, %xmm3
2677         pand    $in1_x(%rsp), %xmm2
2678         pand    $in1_x+0x10(%rsp), %xmm3
2679         por     %xmm0, %xmm2
2680         por     %xmm1, %xmm3
2681         movdqu  %xmm2, 0x00($r_ptr)
2682         movdqu  %xmm3, 0x10($r_ptr)
2683
2684         movdqa  %xmm5, %xmm0            # copy_conditional(res_y, in2_y, in1infty);
2685         movdqa  %xmm5, %xmm1
2686         pandn   $res_y(%rsp), %xmm0
2687         movdqa  %xmm5, %xmm2
2688         pandn   $res_y+0x10(%rsp), %xmm1
2689         movdqa  %xmm5, %xmm3
2690         pand    $in2_y(%rsp), %xmm2
2691         pand    $in2_y+0x10(%rsp), %xmm3
2692         por     %xmm0, %xmm2
2693         por     %xmm1, %xmm3
2694
2695         movdqa  %xmm4, %xmm0            # copy_conditional(res_y, in1_y, in2infty);
2696         movdqa  %xmm4, %xmm1
2697         pandn   %xmm2, %xmm0
2698         movdqa  %xmm4, %xmm2
2699         pandn   %xmm3, %xmm1
2700         movdqa  %xmm4, %xmm3
2701         pand    $in1_y(%rsp), %xmm2
2702         pand    $in1_y+0x10(%rsp), %xmm3
2703         por     %xmm0, %xmm2
2704         por     %xmm1, %xmm3
2705         movdqu  %xmm2, 0x20($r_ptr)
2706         movdqu  %xmm3, 0x30($r_ptr)
2707
2708 .Ladd_done$x:
2709         lea     32*18+56(%rsp), %rsi
2710 .cfi_def_cfa    %rsi,8
2711         mov     -48(%rsi),%r15
2712 .cfi_restore    %r15
2713         mov     -40(%rsi),%r14
2714 .cfi_restore    %r14
2715         mov     -32(%rsi),%r13
2716 .cfi_restore    %r13
2717         mov     -24(%rsi),%r12
2718 .cfi_restore    %r12
2719         mov     -16(%rsi),%rbx
2720 .cfi_restore    %rbx
2721         mov     -8(%rsi),%rbp
2722 .cfi_restore    %rbp
2723         lea     (%rsi),%rsp
2724 .cfi_def_cfa_register   %rsp
2725 .Lpoint_add${x}_epilogue:
2726         ret
2727 .cfi_endproc
2728 .size   ecp_nistz256_point_add$sfx,.-ecp_nistz256_point_add$sfx
2729 ___
2730 }
2731 &gen_add("q");
2732
2733 sub gen_add_affine () {
2734     my $x = shift;
2735     my ($src0,$sfx,$bias);
2736     my ($U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr,
2737         $res_x,$res_y,$res_z,
2738         $in1_x,$in1_y,$in1_z,
2739         $in2_x,$in2_y)=map(32*$_,(0..14));
2740     my $Z1sqr = $S2;
2741
2742     if ($x ne "x") {
2743         $src0 = "%rax";
2744         $sfx  = "";
2745         $bias = 0;
2746
2747 $code.=<<___;
2748 .globl  ecp_nistz256_point_add_affine
2749 .type   ecp_nistz256_point_add_affine,\@function,3
2750 .align  32
2751 ecp_nistz256_point_add_affine:
2752 .cfi_startproc
2753 ___
2754 $code.=<<___    if ($addx);
2755         mov     \$0x80100, %ecx
2756         and     OPENSSL_ia32cap_P+8(%rip), %ecx
2757         cmp     \$0x80100, %ecx
2758         je      .Lpoint_add_affinex
2759 ___
2760     } else {
2761         $src0 = "%rdx";
2762         $sfx  = "x";
2763         $bias = 128;
2764
2765 $code.=<<___;
2766 .type   ecp_nistz256_point_add_affinex,\@function,3
2767 .align  32
2768 ecp_nistz256_point_add_affinex:
2769 .cfi_startproc
2770 .Lpoint_add_affinex:
2771 ___
2772     }
2773 $code.=<<___;
2774         push    %rbp
2775 .cfi_push       %rbp
2776         push    %rbx
2777 .cfi_push       %rbx
2778         push    %r12
2779 .cfi_push       %r12
2780         push    %r13
2781 .cfi_push       %r13
2782         push    %r14
2783 .cfi_push       %r14
2784         push    %r15
2785 .cfi_push       %r15
2786         sub     \$32*15+8, %rsp
2787 .cfi_adjust_cfa_offset  32*15+8
2788 .Ladd_affine${x}_body:
2789
2790         movdqu  0x00($a_ptr), %xmm0     # copy  *(P256_POINT *)$a_ptr
2791         mov     $b_org, $b_ptr          # reassign
2792         movdqu  0x10($a_ptr), %xmm1
2793         movdqu  0x20($a_ptr), %xmm2
2794         movdqu  0x30($a_ptr), %xmm3
2795         movdqu  0x40($a_ptr), %xmm4
2796         movdqu  0x50($a_ptr), %xmm5
2797          mov    0x40+8*0($a_ptr), $src0 # load original in1_z
2798          mov    0x40+8*1($a_ptr), $acc6
2799          mov    0x40+8*2($a_ptr), $acc7
2800          mov    0x40+8*3($a_ptr), $acc0
2801         movdqa  %xmm0, $in1_x(%rsp)
2802         movdqa  %xmm1, $in1_x+0x10(%rsp)
2803         movdqa  %xmm2, $in1_y(%rsp)
2804         movdqa  %xmm3, $in1_y+0x10(%rsp)
2805         movdqa  %xmm4, $in1_z(%rsp)
2806         movdqa  %xmm5, $in1_z+0x10(%rsp)
2807         por     %xmm4, %xmm5
2808
2809         movdqu  0x00($b_ptr), %xmm0     # copy  *(P256_POINT_AFFINE *)$b_ptr
2810          pshufd \$0xb1, %xmm5, %xmm3
2811         movdqu  0x10($b_ptr), %xmm1
2812         movdqu  0x20($b_ptr), %xmm2
2813          por    %xmm3, %xmm5
2814         movdqu  0x30($b_ptr), %xmm3
2815         movdqa  %xmm0, $in2_x(%rsp)
2816          pshufd \$0x1e, %xmm5, %xmm4
2817         movdqa  %xmm1, $in2_x+0x10(%rsp)
2818         por     %xmm0, %xmm1
2819          movq   $r_ptr, %xmm0           # save $r_ptr
2820         movdqa  %xmm2, $in2_y(%rsp)
2821         movdqa  %xmm3, $in2_y+0x10(%rsp)
2822         por     %xmm2, %xmm3
2823          por    %xmm4, %xmm5
2824          pxor   %xmm4, %xmm4
2825         por     %xmm1, %xmm3
2826
2827         lea     0x40-$bias($a_ptr), $a_ptr      # $a_ptr is still valid
2828         lea     $Z1sqr(%rsp), $r_ptr            # Z1^2
2829         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(Z1sqr, in1_z);
2830
2831         pcmpeqd %xmm4, %xmm5
2832         pshufd  \$0xb1, %xmm3, %xmm4
2833          mov    0x00($b_ptr), $src0             # $b_ptr is still valid
2834          #lea   0x00($b_ptr), $b_ptr
2835          mov    $acc4, $acc1                    # harmonize sqr output and mul input
2836         por     %xmm3, %xmm4
2837         pshufd  \$0, %xmm5, %xmm5               # in1infty
2838         pshufd  \$0x1e, %xmm4, %xmm3
2839          mov    $acc5, $acc2
2840         por     %xmm3, %xmm4
2841         pxor    %xmm3, %xmm3
2842          mov    $acc6, $acc3
2843         pcmpeqd %xmm3, %xmm4
2844         pshufd  \$0, %xmm4, %xmm4               # in2infty
2845
2846         lea     $Z1sqr-$bias(%rsp), $a_ptr
2847         mov     $acc7, $acc4
2848         lea     $U2(%rsp), $r_ptr               # U2 = X2*Z1^2
2849         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(U2, Z1sqr, in2_x);
2850
2851         lea     $in1_x(%rsp), $b_ptr
2852         lea     $H(%rsp), $r_ptr                # H = U2 - U1
2853         call    __ecp_nistz256_sub_from$x       # p256_sub(H, U2, in1_x);
2854
2855         `&load_for_mul("$Z1sqr(%rsp)", "$in1_z(%rsp)", "$src0")`
2856         lea     $S2(%rsp), $r_ptr               # S2 = Z1^3
2857         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S2, Z1sqr, in1_z);
2858
2859         `&load_for_mul("$H(%rsp)", "$in1_z(%rsp)", "$src0")`
2860         lea     $res_z(%rsp), $r_ptr            # Z3 = H*Z1*Z2
2861         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(res_z, H, in1_z);
2862
2863         `&load_for_mul("$S2(%rsp)", "$in2_y(%rsp)", "$src0")`
2864         lea     $S2(%rsp), $r_ptr               # S2 = Y2*Z1^3
2865         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S2, S2, in2_y);
2866
2867         lea     $in1_y(%rsp), $b_ptr
2868         lea     $R(%rsp), $r_ptr                # R = S2 - S1
2869         call    __ecp_nistz256_sub_from$x       # p256_sub(R, S2, in1_y);
2870
2871         `&load_for_sqr("$H(%rsp)", "$src0")`
2872         lea     $Hsqr(%rsp), $r_ptr             # H^2
2873         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(Hsqr, H);
2874
2875         `&load_for_sqr("$R(%rsp)", "$src0")`
2876         lea     $Rsqr(%rsp), $r_ptr             # R^2
2877         call    __ecp_nistz256_sqr_mont$x       # p256_sqr_mont(Rsqr, R);
2878
2879         `&load_for_mul("$H(%rsp)", "$Hsqr(%rsp)", "$src0")`
2880         lea     $Hcub(%rsp), $r_ptr             # H^3
2881         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(Hcub, Hsqr, H);
2882
2883         `&load_for_mul("$Hsqr(%rsp)", "$in1_x(%rsp)", "$src0")`
2884         lea     $U2(%rsp), $r_ptr               # U1*H^2
2885         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(U2, in1_x, Hsqr);
2886 ___
2887 {
2888 #######################################################################
2889 # operate in 4-5-0-1 "name space" that matches multiplication output
2890 #
2891 my ($acc0,$acc1,$acc2,$acc3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3);
2892 my ($poly1, $poly3)=($acc6,$acc7);
2893
2894 $code.=<<___;
2895         #lea    $U2(%rsp), $a_ptr
2896         #lea    $Hsqr(%rsp), $r_ptr     # 2*U1*H^2
2897         #call   __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2);
2898
2899         xor     $t4, $t4
2900         add     $acc0, $acc0            # a0:a3+a0:a3
2901         lea     $Rsqr(%rsp), $a_ptr
2902         adc     $acc1, $acc1
2903          mov    $acc0, $t0
2904         adc     $acc2, $acc2
2905         adc     $acc3, $acc3
2906          mov    $acc1, $t1
2907         adc     \$0, $t4
2908
2909         sub     \$-1, $acc0
2910          mov    $acc2, $t2
2911         sbb     $poly1, $acc1
2912         sbb     \$0, $acc2
2913          mov    $acc3, $t3
2914         sbb     $poly3, $acc3
2915         sbb     \$0, $t4
2916
2917         cmovc   $t0, $acc0
2918         mov     8*0($a_ptr), $t0
2919         cmovc   $t1, $acc1
2920         mov     8*1($a_ptr), $t1
2921         cmovc   $t2, $acc2
2922         mov     8*2($a_ptr), $t2
2923         cmovc   $t3, $acc3
2924         mov     8*3($a_ptr), $t3
2925
2926         call    __ecp_nistz256_sub$x            # p256_sub(res_x, Rsqr, Hsqr);
2927
2928         lea     $Hcub(%rsp), $b_ptr
2929         lea     $res_x(%rsp), $r_ptr
2930         call    __ecp_nistz256_sub_from$x       # p256_sub(res_x, res_x, Hcub);
2931
2932         mov     $U2+8*0(%rsp), $t0
2933         mov     $U2+8*1(%rsp), $t1
2934         mov     $U2+8*2(%rsp), $t2
2935         mov     $U2+8*3(%rsp), $t3
2936         lea     $H(%rsp), $r_ptr
2937
2938         call    __ecp_nistz256_sub$x            # p256_sub(H, U2, res_x);
2939
2940         mov     $acc0, 8*0($r_ptr)              # save the result, as
2941         mov     $acc1, 8*1($r_ptr)              # __ecp_nistz256_sub doesn't
2942         mov     $acc2, 8*2($r_ptr)
2943         mov     $acc3, 8*3($r_ptr)
2944 ___
2945 }
2946 $code.=<<___;
2947         `&load_for_mul("$Hcub(%rsp)", "$in1_y(%rsp)", "$src0")`
2948         lea     $S2(%rsp), $r_ptr
2949         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(S2, Hcub, in1_y);
2950
2951         `&load_for_mul("$H(%rsp)", "$R(%rsp)", "$src0")`
2952         lea     $H(%rsp), $r_ptr
2953         call    __ecp_nistz256_mul_mont$x       # p256_mul_mont(H, H, R);
2954
2955         lea     $S2(%rsp), $b_ptr
2956         lea     $res_y(%rsp), $r_ptr
2957         call    __ecp_nistz256_sub_from$x       # p256_sub(res_y, H, S2);
2958
2959         movq    %xmm0, $r_ptr           # restore $r_ptr
2960
2961         movdqa  %xmm5, %xmm0            # copy_conditional(res_z, ONE, in1infty);
2962         movdqa  %xmm5, %xmm1
2963         pandn   $res_z(%rsp), %xmm0
2964         movdqa  %xmm5, %xmm2
2965         pandn   $res_z+0x10(%rsp), %xmm1
2966         movdqa  %xmm5, %xmm3
2967         pand    .LONE_mont(%rip), %xmm2
2968         pand    .LONE_mont+0x10(%rip), %xmm3
2969         por     %xmm0, %xmm2
2970         por     %xmm1, %xmm3
2971
2972         movdqa  %xmm4, %xmm0            # copy_conditional(res_z, in1_z, in2infty);
2973         movdqa  %xmm4, %xmm1
2974         pandn   %xmm2, %xmm0
2975         movdqa  %xmm4, %xmm2
2976         pandn   %xmm3, %xmm1
2977         movdqa  %xmm4, %xmm3
2978         pand    $in1_z(%rsp), %xmm2
2979         pand    $in1_z+0x10(%rsp), %xmm3
2980         por     %xmm0, %xmm2
2981         por     %xmm1, %xmm3
2982         movdqu  %xmm2, 0x40($r_ptr)
2983         movdqu  %xmm3, 0x50($r_ptr)
2984
2985         movdqa  %xmm5, %xmm0            # copy_conditional(res_x, in2_x, in1infty);
2986         movdqa  %xmm5, %xmm1
2987         pandn   $res_x(%rsp), %xmm0
2988         movdqa  %xmm5, %xmm2
2989         pandn   $res_x+0x10(%rsp), %xmm1
2990         movdqa  %xmm5, %xmm3
2991         pand    $in2_x(%rsp), %xmm2
2992         pand    $in2_x+0x10(%rsp), %xmm3
2993         por     %xmm0, %xmm2
2994         por     %xmm1, %xmm3
2995
2996         movdqa  %xmm4, %xmm0            # copy_conditional(res_x, in1_x, in2infty);
2997         movdqa  %xmm4, %xmm1
2998         pandn   %xmm2, %xmm0
2999         movdqa  %xmm4, %xmm2
3000         pandn   %xmm3, %xmm1
3001         movdqa  %xmm4, %xmm3
3002         pand    $in1_x(%rsp), %xmm2
3003         pand    $in1_x+0x10(%rsp), %xmm3
3004         por     %xmm0, %xmm2
3005         por     %xmm1, %xmm3
3006         movdqu  %xmm2, 0x00($r_ptr)
3007         movdqu  %xmm3, 0x10($r_ptr)
3008
3009         movdqa  %xmm5, %xmm0            # copy_conditional(res_y, in2_y, in1infty);
3010         movdqa  %xmm5, %xmm1
3011         pandn   $res_y(%rsp), %xmm0
3012         movdqa  %xmm5, %xmm2
3013         pandn   $res_y+0x10(%rsp), %xmm1
3014         movdqa  %xmm5, %xmm3
3015         pand    $in2_y(%rsp), %xmm2
3016         pand    $in2_y+0x10(%rsp), %xmm3
3017         por     %xmm0, %xmm2
3018         por     %xmm1, %xmm3
3019
3020         movdqa  %xmm4, %xmm0            # copy_conditional(res_y, in1_y, in2infty);
3021         movdqa  %xmm4, %xmm1
3022         pandn   %xmm2, %xmm0
3023         movdqa  %xmm4, %xmm2
3024         pandn   %xmm3, %xmm1
3025         movdqa  %xmm4, %xmm3
3026         pand    $in1_y(%rsp), %xmm2
3027         pand    $in1_y+0x10(%rsp), %xmm3
3028         por     %xmm0, %xmm2
3029         por     %xmm1, %xmm3
3030         movdqu  %xmm2, 0x20($r_ptr)
3031         movdqu  %xmm3, 0x30($r_ptr)
3032
3033         lea     32*15+56(%rsp), %rsi
3034 .cfi_def_cfa    %rsi,8
3035         mov     -48(%rsi),%r15
3036 .cfi_restore    %r15
3037         mov     -40(%rsi),%r14
3038 .cfi_restore    %r14
3039         mov     -32(%rsi),%r13
3040 .cfi_restore    %r13
3041         mov     -24(%rsi),%r12
3042 .cfi_restore    %r12
3043         mov     -16(%rsi),%rbx
3044 .cfi_restore    %rbx
3045         mov     -8(%rsi),%rbp
3046 .cfi_restore    %rbp
3047         lea     (%rsi),%rsp
3048 .cfi_def_cfa_register   %rsp
3049 .Ladd_affine${x}_epilogue:
3050         ret
3051 .cfi_endproc
3052 .size   ecp_nistz256_point_add_affine$sfx,.-ecp_nistz256_point_add_affine$sfx
3053 ___
3054 }
3055 &gen_add_affine("q");
3056
3057 ########################################################################
3058 # AD*X magic
3059 #
3060 if ($addx) {                                                            {
3061 ########################################################################
3062 # operate in 4-5-0-1 "name space" that matches multiplication output
3063 #
3064 my ($a0,$a1,$a2,$a3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3);
3065
3066 $code.=<<___;
3067 .type   __ecp_nistz256_add_tox,\@abi-omnipotent
3068 .align  32
3069 __ecp_nistz256_add_tox:
3070         xor     $t4, $t4
3071         adc     8*0($b_ptr), $a0
3072         adc     8*1($b_ptr), $a1
3073          mov    $a0, $t0
3074         adc     8*2($b_ptr), $a2
3075         adc     8*3($b_ptr), $a3
3076          mov    $a1, $t1
3077         adc     \$0, $t4
3078
3079         xor     $t3, $t3
3080         sbb     \$-1, $a0
3081          mov    $a2, $t2
3082         sbb     $poly1, $a1
3083         sbb     \$0, $a2
3084          mov    $a3, $t3
3085         sbb     $poly3, $a3
3086         sbb     \$0, $t4
3087
3088         cmovc   $t0, $a0
3089         cmovc   $t1, $a1
3090         mov     $a0, 8*0($r_ptr)
3091         cmovc   $t2, $a2
3092         mov     $a1, 8*1($r_ptr)
3093         cmovc   $t3, $a3
3094         mov     $a2, 8*2($r_ptr)
3095         mov     $a3, 8*3($r_ptr)
3096
3097         ret
3098 .size   __ecp_nistz256_add_tox,.-__ecp_nistz256_add_tox
3099
3100 .type   __ecp_nistz256_sub_fromx,\@abi-omnipotent
3101 .align  32
3102 __ecp_nistz256_sub_fromx:
3103         xor     $t4, $t4
3104         sbb     8*0($b_ptr), $a0
3105         sbb     8*1($b_ptr), $a1
3106          mov    $a0, $t0
3107         sbb     8*2($b_ptr), $a2
3108         sbb     8*3($b_ptr), $a3
3109          mov    $a1, $t1
3110         sbb     \$0, $t4
3111
3112         xor     $t3, $t3
3113         adc     \$-1, $a0
3114          mov    $a2, $t2
3115         adc     $poly1, $a1
3116         adc     \$0, $a2
3117          mov    $a3, $t3
3118         adc     $poly3, $a3
3119
3120         bt      \$0, $t4
3121         cmovnc  $t0, $a0
3122         cmovnc  $t1, $a1
3123         mov     $a0, 8*0($r_ptr)
3124         cmovnc  $t2, $a2
3125         mov     $a1, 8*1($r_ptr)
3126         cmovnc  $t3, $a3
3127         mov     $a2, 8*2($r_ptr)
3128         mov     $a3, 8*3($r_ptr)
3129
3130         ret
3131 .size   __ecp_nistz256_sub_fromx,.-__ecp_nistz256_sub_fromx
3132
3133 .type   __ecp_nistz256_subx,\@abi-omnipotent
3134 .align  32
3135 __ecp_nistz256_subx:
3136         xor     $t4, $t4
3137         sbb     $a0, $t0
3138         sbb     $a1, $t1
3139          mov    $t0, $a0
3140         sbb     $a2, $t2
3141         sbb     $a3, $t3
3142          mov    $t1, $a1
3143         sbb     \$0, $t4
3144
3145         xor     $a3 ,$a3
3146         adc     \$-1, $t0
3147          mov    $t2, $a2
3148         adc     $poly1, $t1
3149         adc     \$0, $t2
3150          mov    $t3, $a3
3151         adc     $poly3, $t3
3152
3153         bt      \$0, $t4
3154         cmovc   $t0, $a0
3155         cmovc   $t1, $a1
3156         cmovc   $t2, $a2
3157         cmovc   $t3, $a3
3158
3159         ret
3160 .size   __ecp_nistz256_subx,.-__ecp_nistz256_subx
3161
3162 .type   __ecp_nistz256_mul_by_2x,\@abi-omnipotent
3163 .align  32
3164 __ecp_nistz256_mul_by_2x:
3165         xor     $t4, $t4
3166         adc     $a0, $a0                # a0:a3+a0:a3
3167         adc     $a1, $a1
3168          mov    $a0, $t0
3169         adc     $a2, $a2
3170         adc     $a3, $a3
3171          mov    $a1, $t1
3172         adc     \$0, $t4
3173
3174         xor     $t3, $t3
3175         sbb     \$-1, $a0
3176          mov    $a2, $t2
3177         sbb     $poly1, $a1
3178         sbb     \$0, $a2
3179          mov    $a3, $t3
3180         sbb     $poly3, $a3
3181         sbb     \$0, $t4
3182
3183         cmovc   $t0, $a0
3184         cmovc   $t1, $a1
3185         mov     $a0, 8*0($r_ptr)
3186         cmovc   $t2, $a2
3187         mov     $a1, 8*1($r_ptr)
3188         cmovc   $t3, $a3
3189         mov     $a2, 8*2($r_ptr)
3190         mov     $a3, 8*3($r_ptr)
3191
3192         ret
3193 .size   __ecp_nistz256_mul_by_2x,.-__ecp_nistz256_mul_by_2x
3194 ___
3195                                                                         }
3196 &gen_double("x");
3197 &gen_add("x");
3198 &gen_add_affine("x");
3199 }
3200 }}}
3201
3202 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
3203 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
3204 if ($win64) {
3205 $rec="%rcx";
3206 $frame="%rdx";
3207 $context="%r8";
3208 $disp="%r9";
3209
3210 $code.=<<___;
3211 .extern __imp_RtlVirtualUnwind
3212
3213 .type   short_handler,\@abi-omnipotent
3214 .align  16
3215 short_handler:
3216         push    %rsi
3217         push    %rdi
3218         push    %rbx
3219         push    %rbp
3220         push    %r12
3221         push    %r13
3222         push    %r14
3223         push    %r15
3224         pushfq
3225         sub     \$64,%rsp
3226
3227         mov     120($context),%rax      # pull context->Rax
3228         mov     248($context),%rbx      # pull context->Rip
3229
3230         mov     8($disp),%rsi           # disp->ImageBase
3231         mov     56($disp),%r11          # disp->HandlerData
3232
3233         mov     0(%r11),%r10d           # HandlerData[0]
3234         lea     (%rsi,%r10),%r10        # end of prologue label
3235         cmp     %r10,%rbx               # context->Rip<end of prologue label
3236         jb      .Lcommon_seh_tail
3237
3238         mov     152($context),%rax      # pull context->Rsp
3239
3240         mov     4(%r11),%r10d           # HandlerData[1]
3241         lea     (%rsi,%r10),%r10        # epilogue label
3242         cmp     %r10,%rbx               # context->Rip>=epilogue label
3243         jae     .Lcommon_seh_tail
3244
3245         lea     16(%rax),%rax
3246
3247         mov     -8(%rax),%r12
3248         mov     -16(%rax),%r13
3249         mov     %r12,216($context)      # restore context->R12
3250         mov     %r13,224($context)      # restore context->R13
3251
3252         jmp     .Lcommon_seh_tail
3253 .size   short_handler,.-short_handler
3254
3255 .type   full_handler,\@abi-omnipotent
3256 .align  16
3257 full_handler:
3258         push    %rsi
3259         push    %rdi
3260         push    %rbx
3261         push    %rbp
3262         push    %r12
3263         push    %r13
3264         push    %r14
3265         push    %r15
3266         pushfq
3267         sub     \$64,%rsp
3268
3269         mov     120($context),%rax      # pull context->Rax
3270         mov     248($context),%rbx      # pull context->Rip
3271
3272         mov     8($disp),%rsi           # disp->ImageBase
3273         mov     56($disp),%r11          # disp->HandlerData
3274
3275         mov     0(%r11),%r10d           # HandlerData[0]
3276         lea     (%rsi,%r10),%r10        # end of prologue label
3277         cmp     %r10,%rbx               # context->Rip<end of prologue label
3278         jb      .Lcommon_seh_tail
3279
3280         mov     152($context),%rax      # pull context->Rsp
3281
3282         mov     4(%r11),%r10d           # HandlerData[1]
3283         lea     (%rsi,%r10),%r10        # epilogue label
3284         cmp     %r10,%rbx               # context->Rip>=epilogue label
3285         jae     .Lcommon_seh_tail
3286
3287         mov     8(%r11),%r10d           # HandlerData[2]
3288         lea     (%rax,%r10),%rax
3289
3290         mov     -8(%rax),%rbp
3291         mov     -16(%rax),%rbx
3292         mov     -24(%rax),%r12
3293         mov     -32(%rax),%r13
3294         mov     -40(%rax),%r14
3295         mov     -48(%rax),%r15
3296         mov     %rbx,144($context)      # restore context->Rbx
3297         mov     %rbp,160($context)      # restore context->Rbp
3298         mov     %r12,216($context)      # restore context->R12
3299         mov     %r13,224($context)      # restore context->R13
3300         mov     %r14,232($context)      # restore context->R14
3301         mov     %r15,240($context)      # restore context->R15
3302
3303 .Lcommon_seh_tail:
3304         mov     8(%rax),%rdi
3305         mov     16(%rax),%rsi
3306         mov     %rax,152($context)      # restore context->Rsp
3307         mov     %rsi,168($context)      # restore context->Rsi
3308         mov     %rdi,176($context)      # restore context->Rdi
3309
3310         mov     40($disp),%rdi          # disp->ContextRecord
3311         mov     $context,%rsi           # context
3312         mov     \$154,%ecx              # sizeof(CONTEXT)
3313         .long   0xa548f3fc              # cld; rep movsq
3314
3315         mov     $disp,%rsi
3316         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
3317         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
3318         mov     0(%rsi),%r8             # arg3, disp->ControlPc
3319         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
3320         mov     40(%rsi),%r10           # disp->ContextRecord
3321         lea     56(%rsi),%r11           # &disp->HandlerData
3322         lea     24(%rsi),%r12           # &disp->EstablisherFrame
3323         mov     %r10,32(%rsp)           # arg5
3324         mov     %r11,40(%rsp)           # arg6
3325         mov     %r12,48(%rsp)           # arg7
3326         mov     %rcx,56(%rsp)           # arg8, (NULL)
3327         call    *__imp_RtlVirtualUnwind(%rip)
3328
3329         mov     \$1,%eax                # ExceptionContinueSearch
3330         add     \$64,%rsp
3331         popfq
3332         pop     %r15
3333         pop     %r14
3334         pop     %r13
3335         pop     %r12
3336         pop     %rbp
3337         pop     %rbx
3338         pop     %rdi
3339         pop     %rsi
3340         ret
3341 .size   full_handler,.-full_handler
3342
3343 .section        .pdata