• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 *     http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16#include "hitls_build.h"
17#ifdef HITLS_CRYPTO_BN
18
19.file   "bn_mont_x86_64.S"
20.text
21
22.macro  ADD_CARRY a b
23    addq    \a,\b
24    adcq    $0,%rdx
25.endm
26
27.macro  SAVE_REGISTERS
28    pushq   %r15                        // Save non-volatile register.
29    pushq   %r14
30    pushq   %r13
31    pushq   %r12
32    pushq   %rbp
33    pushq   %rbx
34.endm
35
36.macro  RESTORE_REGISTERS
37    popq    %rbx              // Restore non-volatile register.
38    popq    %rbp
39    popq    %r12
40    popq    %r13
41    popq    %r14
42    popq    %r15
43.endm
44
45/*
46* void MontMul_Asm(uint64_t *r, const uint64_t *a, const uint64_t *b,
47*                     const uint64_t *n, const uint64_t k0, uint32_t size);
48*/
49.globl  MontMul_Asm
50.type   MontMul_Asm,@function
51.align  16
52MontMul_Asm:
53.cfi_startproc
54    testl   $3,%r9d
55    jnz     .LMontMul                   // If size is not divisible by 4, LMontMul.
56    cmpl    $8,%r9d
57    jb      .LMontMul                   // LMontMul
58    cmpq    %rsi,%rdx
59    jne     MontMul4                    // if a != b, MontMul4
60    testl   $7,%r9d
61    jz      MontSqr8                    // If size is divisible by 8,enter MontSqr8.
62    jmp     MontMul4
63
64.align  16
65.LMontMul:
66    SAVE_REGISTERS                          // Save non-volatile register.
67    movq    %rsp,%rax                       // rax stores the rsp
68
69    movq    %r9, %r15
70    negq    %r15                            // r15 = -size
71    leaq    -16(%rsp, %r15, 8), %r15        // r15 = rsp - size * 8 - 16
72    andq    $-1024, %r15                    // r15 The address is aligned down by 1 KB.
73    movq    %rsp, %r14                      // r14 = rsp
74
75    subq    %r15,%r14                       // __chkstk implemention, called when the stack size needs to exceed 4096.
76                                            // (the size of a page) to allocate more pages.
77    andq    $-4096,%r14                     // r14 4K down-align.
78    leaq    (%r15,%r14),%rsp                // rsp = r15 + r14
79    cmpq    %r15,%rsp                       // If you want to allocate more than one page, go to Lmul_page_walk.
80    ja      .LoopPage
81    jmp     .LMulBody
82
83.align  16
84.LoopPage:
85    leaq    -4096(%rsp),%rsp            // rsp - 4096 each time until rsp < r15.
86    cmpq    %r15,%rsp
87    ja      .LoopPage
88
89.LMulBody:
90    movq    %rax,8(%rsp,%r9,8)          // Save the original rsp in the stack.
91    movq    %rdx,%r13                   // r13 = b
92
93    xorq    %r11,%r11                   // r11 = 0
94    xorq    %r10,%r10                   // r10 = 0
95
96    movq    (%r13),%rbx                 // rbx = b[0]
97    movq    (%rsi),%rax                 // rax = a[0]
98    mulq    %rbx                        // (rdx, rax) = a[0] * b[0]
99    movq    %rax,%r15                   // r15 = t[0] = lo(a[0] * b[0])
100    movq    %rdx,%r14                   // r14 = hi(a[0] * b[0])
101
102    movq    %r8,%rbp                    // rbp = k0
103    imulq   %r15,%rbp                   // rbp = t[0] * k0
104    movq    (%rcx),%rax                 // rax = n[0]
105    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[0]
106    ADD_CARRY    %rax,%r15              // r15 = lo(t[0] * k0 * n[0]) + t[0]
107
108    leaq    1(%r10),%r10                // j++
109
110.Loop1st:
111    movq    (%rsi,%r10,8),%rax          // rax = a[j]
112    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[0])
113
114    mulq    %rbx                        // (rdx, rax) = a[j] * b[0]
115    ADD_CARRY    %rax,%r14              // r14 = hi(a[j - 1] * b[0]) + lo(a[j] * b[0])
116    movq    %rdx,%r15                   // r15 = hi(a[j] * b[0])
117
118    movq    (%rcx,%r10,8),%rax          // rax = n[j]
119    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j]
120    leaq    1(%r10),%r10                // j++
121    cmpq    %r9,%r10                    // if j != size, loop L1st
122    je      .Loop1stSkip
123
124    ADD_CARRY    %rax,%r12              // r12 = hi(t[0] * k0 * n[j]) + lo(t[0] * k0 * n[j])
125    ADD_CARRY    %r14,%r12              // r12 += lo(a[j] * b[0]) + hi(a[j] * b[0])
126    movq    %r12,-16(%rsp,%r10,8)       // t[j - 2] = r13
127    movq    %r15,%r14                   // r14 = hi(a[j] * b[0])
128    jmp     .Loop1st
129
130.Loop1stSkip:
131    ADD_CARRY    %rax,%r12              // r12 = hi(t[0] * k0 * n[j - 1]) + lo(t[0] * k0 * n[j])
132    ADD_CARRY    %r14,%r12              // r12 += hi(a[j - 1] * b[0]) + lo(a[j] * b[0])
133    movq    %r12,-16(%rsp,%r10,8)       // t[j - 2] = r13
134    movq    %r15,%r14                   // r14 = hi(a[j] * b[0])
135
136    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j])
137    xorq    %rdx,%rdx                   // rdx = 0, Clearing the CF.
138    ADD_CARRY    %r14,%r12              // r12 = hi(t[0] * k0 * n[j]) + hi(a[j] * b[0])
139    movq    %r12,-8(%rsp,%r9,8)         // t[size - 1] = hi(t[0] * k0 * n[j]) + hi(a[j] * b[0]), save overflow bit.
140    movq    %rdx,(%rsp,%r9,8)
141
142    leaq    1(%r11),%r11                // i++
143
144.align  16
145.LoopOuter:
146    xorq    %r10,%r10                   // j = 0
147    movq    (%rsi),%rax                 // rax = a[0]
148    movq    (%r13,%r11,8),%rbx          // rbx = b[i]
149    mulq    %rbx                        // (rdx, rax) = a[0] * b[i]
150    movq    (%rsp),%r15                 // r15 = lo(a[0] * b[i]) + t[0]
151    ADD_CARRY    %rax,%r15
152    movq    %rdx,%r14                   // r14 = hi(a[0] * b[i])
153
154    movq    %r8,%rbp                    // rbp = t[0] * k0
155    imulq   %r15,%rbp
156    movq    (%rcx),%rax                 // rax = n[0]
157    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[0]
158    ADD_CARRY    %rax,%r15              // r15 = lo(t[0] * k0 * n[0])
159
160    leaq    1(%r10),%r10                // j++
161
162.align  16
163.LoopInner:
164    movq    (%rsi,%r10,8),%rax          // rax = a[j]
165    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j])
166    movq    (%rsp,%r10,8),%r15          // r15 = t[j]
167
168    mulq    %rbx                        // (rdx, rax) = a[1] * b[i]
169    ADD_CARRY    %rax,%r14              // r14 = hi(a[0] * b[i]) + lo(a[1] * b[i])
170    movq    (%rcx,%r10,8),%rax          // rax = n[j]
171    ADD_CARRY    %r14,%r15              // r15 = a[j] * b[i] + t[j]
172    movq    %rdx,%r14
173    leaq    1(%r10),%r10                // j++
174
175    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j]
176    cmpq    %r9,%r10                    // if j != size, loop Linner
177    je      .LoopInnerSkip
178
179    ADD_CARRY    %rax,%r12              // r12 = t[0] * k0 * n[j]
180    ADD_CARRY    %r15,%r12              // r12 = a[j] * b[i] + t[j] + n[j] * t[0] * k0
181    movq    %r12,-16(%rsp,%r10,8)       // t[j - 2] = r13
182    jmp     .LoopInner
183
184.LoopInnerSkip:
185    ADD_CARRY    %rax,%r12              // r12 = t[0] * k0 * n[j]
186    ADD_CARRY    %r15,%r12              // r12 = t[0] * k0 * n[j] + a[j] * b[i] + t[j]
187    movq    (%rsp,%r10,8),%r15          // r15 = t[j]
188    movq    %r12,-16(%rsp,%r10,8)       // t[j - 2]
189    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j])
190
191    xorq    %rdx,%rdx                   // rdx 0
192    ADD_CARRY    %r14,%r12              // r12 = hi(a[1] * b[i]) + hi(t[0] * k0 * n[j])
193    ADD_CARRY    %r15,%r12              // r12 += t[j]
194    movq    %r12,-8(%rsp,%r9,8)         // t[size - 1] = r13
195    movq    %rdx,(%rsp,%r9,8)           // t[size] = CF
196
197    leaq    1(%r11),%r11                // i++
198    cmpq    %r9,%r11                    // if size < i (unsigned)
199    jne     .LoopOuter
200
201    xorq    %r11,%r11                   // r11 = 0, clear CF.
202    movq    (%rsp),%rax                 // rax = t[0]
203    movq    %r9,%r10                    // r10 = size
204
205.align  16
206.LoopSub:
207    sbbq    (%rcx,%r11,8),%rax          // r[i] = t[i] - n[i]
208    movq    %rax,(%rdi,%r11,8)
209    movq    8(%rsp,%r11,8),%rax         // rax = t[i + 1]
210
211    leaq    1(%r11),%r11                // i++
212    decq    %r10                        // j--
213    jnz     .LoopSub                    // if j != 0
214
215    sbbq    $0,%rax                     // rax -= CF
216    movq    $-1,%rbx
217    xorq    %rax,%rbx                   // rbx = !t[i + 1]
218    xorq    %r11,%r11                   // r11 = 0
219    movq    %r9,%r10                    // r10 = size
220
221.LoopCopy:
222    movq    (%rdi,%r11,8),%rcx          // rcx = r[i] & t[i]
223    andq    %rbx,%rcx
224    movq    (%rsp,%r11,8),%rdx          // rdx = CF & t[i]
225    andq    %rax,%rdx
226    orq     %rcx,%rdx
227    movq    %rdx,(%rdi,%r11,8)          // r[i] = t[i]
228    movq    %r9,(%rsp,%r11,8)           // t[i] = size
229    leaq    1(%r11),%r11                // i++
230    subq    $1,%r10                     // j--
231    jnz     .LoopCopy                   // if j != 0
232
233    movq    8(%rsp,%r9,8),%rsi          // rsi = pressed-stacked rsp.
234    movq    $1,%rax                     // rax = 1
235    leaq    (%rsi),%rsp                 // restore rsp.
236    RESTORE_REGISTERS                   // Restore non-volatile register.
237    ret
238.cfi_endproc
239.size   MontMul_Asm,.-MontMul_Asm
240
241.type   MontMul4,@function
242.align  16
243MontMul4:
244.cfi_startproc
245    SAVE_REGISTERS
246    movq    %rsp,%rax                   // save rsp
247
248    movq    %r9,%r15
249    negq    %r15
250    leaq    -32(%rsp,%r15,8),%r15       // Allocate space: size * 8 + 32 bytes.
251    andq    $-1024,%r15
252    movq    %rsp,%r14
253
254    subq    %r15,%r14                   // __chkstk implemention, called when the stack size needs to exceed 4096.
255    andq    $-4096,%r14
256    leaq    (%r15,%r14),%rsp
257    cmpq    %r15,%rsp                   // If you want to allocate more than one page, go to LoopPage4x.
258    ja      .LoopPage4x
259    jmp     .LoopMul4x
260
261.LoopPage4x:
262    leaq    -4096(%rsp),%rsp            // rsp - 4096each time until rsp >= r10.
263    cmpq    %r15,%rsp
264    ja      .LoopPage4x
265
266.LoopMul4x:
267    xorq    %r11,%r11                   // i = 0
268    xorq    %r10,%r10                   // j = 0
269
270    movq    %rax,8(%rsp,%r9,8)
271    movq    %rdi,16(%rsp,%r9,8)         // t[size + 2] = r
272    movq    %rdx,%r13                   // r13 = b
273    movq    (%rsi),%rax                 // rax = a[0]
274    movq    %r8,%rbp                    // rbp = k0
275    movq    (%r13),%rbx                 // rbx = b[0]
276
277    /* 计算a[i] * b[0] * k[0] * n[j] */
278    mulq    %rbx                        // (rdx, rax) = a[0] * b[0]
279    movq    %rax,%r15                   // r15 = t[0] = lo(b[0] * a[0])
280    movq    (%rcx),%rax                 // rax = n[0]
281
282    imulq   %r15,%rbp                   // rbp = t[0] * k0
283    movq    %rdx,%r14                   // r14 = hi(a[0] * b[0])
284
285    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[0]
286    ADD_CARRY    %rax,%r15              // r15 = lo(t[0] * k0 * n[0])
287    movq    8(%rsi),%rax                // rax = a[1]
288    movq    %rdx,%rdi                   // rdi = hi(t[0] * k0 * n[0])
289
290    mulq    %rbx                        // (rdx, rax) = a[1] * b[0]
291    ADD_CARRY    %rax,%r14              // r14 = lo(a[1] * b[0]) + hi(a[0] * b[0])
292    movq    8(%rcx),%rax                // rax = n[1]
293    movq    %rdx,%r15                   // r15 = hi(a[1] * b[0])
294
295    mulq    %rbp                        // (rdx, rax) =  t[0] * k0 * n[1]
296    ADD_CARRY    %rax,%rdi              // rdi = lo(t[0] * k0 * n[1]) + hi(t[0] * k0 * n[0])
297    movq    16(%rsi),%rax               // rax = a[2]
298    ADD_CARRY    %r14,%rdi              // rdi += hi(a[0] * b[0]) + lo(a[1] * b[0])
299    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[1])
300    movq    %rdi,(%rsp)                 // t[0] = rdi
301
302    leaq    4(%r10),%r10                // j += 4
303
304.align  16
305.Loop1st4x:
306    mulq    %rbx                        // (rdx, rax) = a[2] * b[0]
307    ADD_CARRY    %rax,%r15              // r15 = hi(a[1] * b[0]) + lo(a[2] * b[0])
308    movq    -16(%rcx,%r10,8),%rax       // rax = n[j - 2]
309    movq    %rdx,%r14                   // r14 = hi[a[2] * b[0]]
310
311    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j - 2]
312    ADD_CARRY    %rax,%r12              // r12 = hi(t[0] * k0 * n[1]) + lo(t[0] * k0 * n[j - 2])
313    movq    -8(%rsi,%r10,8),%rax        // rax = a[j - 1]
314    ADD_CARRY    %r15,%r12              // r12 += hi(a[1] * b[0]) + lo(a[2] * b[0])
315    movq    %r12,-24(%rsp,%r10,8)       // t[j - 3] = r13
316    movq    %rdx,%rdi                   // rdi = hi(t[0] * k0 * n[j - 2])
317
318    mulq    %rbx                        // (rdx, rax) = a[j - 1] * b[0]
319    ADD_CARRY    %rax,%r14              // r14 = hi[a[2] * b[0]] + lo(a[j - 1] * b[0])
320    movq    -8(%rcx,%r10,8),%rax        // rax = n[j - 1]
321    movq    %rdx,%r15                   // r15 = hi(a[j - 1] * b[0])
322
323    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j - 1]
324    ADD_CARRY    %rax,%rdi              // rdi = hi(t[0] * k0 * n[j - 2]) + lo(t[0] * k0 * n[j - 1]
325    movq    (%rsi,%r10,8),%rax          // rax = a[j]
326    ADD_CARRY    %r14,%rdi              // rdi += hi[a[2] * b[0]] + lo(a[j - 1] * b[0])
327    movq    %rdi,-16(%rsp,%r10,8)       // t[j - 2] = rdi
328    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j - 1])
329
330    mulq    %rbx                        // (rdx, rax) = a[j] * b[0]
331    ADD_CARRY    %rax,%r15              // r15 = hi(a[j - 1] * b[0]) + lo(a[j] * b[0])
332    movq    (%rcx,%r10,8),%rax          // rax = n[j]
333    movq    %rdx,%r14                   // r14 = hi(a[j] * b[0])
334
335    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j]
336    ADD_CARRY    %rax,%r12              // r12 = hi(t[0] * k0 * n[j - 1]) + lo(t[0] * k0 * n[j])
337    movq    8(%rsi,%r10,8),%rax         // rax = a[j + 1]
338    ADD_CARRY    %r15,%r12              // r12 +=  hi(a[j - 1] * b[0]) + lo(a[j] * b[0])
339    movq    %r12,-8(%rsp,%r10,8)        // t[j - 1] = r13
340    movq    %rdx,%rdi                   // rdi = hi(t[0] * k0 * n[j])
341
342    mulq    %rbx                        // (rdx, rax) = a[j + 1] * b[0]
343    ADD_CARRY    %rax,%r14              // r14 = hi(a[j] * b[0]) + lo(a[j + 1] * b[0])
344    movq    8(%rcx,%r10,8),%rax         // rax = n[j + 1]
345    movq    %rdx,%r15                   // r15 = hi(a[j + 1] * b[0])
346
347    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j + 1]
348    ADD_CARRY    %rax,%rdi                  // rdi = hi(t[0] * k0 * n[j]) + lo(t[0] * k0 * n[j + 1])
349    movq    16(%rsi,%r10,8),%rax        // rax = a[j + 2]
350    ADD_CARRY    %r14,%rdi                  // rdi += hi(a[j] * b[0]) + lo(a[j + 1] * b[0])
351    movq    %rdi,(%rsp,%r10,8)          // t[j - 4] = rdi
352    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j + 1])
353
354    leaq    4(%r10),%r10                // j += 4
355    cmpq    %r9,%r10                    // if size != j
356    jb      .Loop1st4x
357
358    mulq    %rbx                        // (rdx, rax) = a[j - 2] * b[0]
359    ADD_CARRY    %rax,%r15              // r15 = hi(a[j - 3] * b[0]) + lo(a[j - 2] * b[0])
360    movq    -16(%rcx,%r10,8),%rax       // rax = n[j - 2]
361    movq    %rdx,%r14                   // r14 = hi(a[j - 2] * b[0])
362
363    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j - 2]
364    ADD_CARRY    %rax,%r12              // r12 = hi(t[0] * k0 * n[j - 3]) + lo(t[0] * k0 * n[j - 2])
365    movq    -8(%rsi,%r10,8),%rax        // rax = a[j - 1]
366    ADD_CARRY    %r15,%r12              // r12 += hi(a[j - 3] * b[0]) + lo(a[j - 2] * b[0])
367    movq    %r12,-24(%rsp,%r10,8)       // t[j - 3] = r13
368    movq    %rdx,%rdi                   // rdi = hi(t[0] * k0 * n[j - 2])
369
370    mulq    %rbx                        // (rdx, rax) =  a[j - 1] * b[0]
371    ADD_CARRY    %rax,%r14              // r14 = hi(a[j - 2] * b[0]) + lo(a[j- 1] * b[0])
372    movq    -8(%rcx,%r10,8),%rax        // rax = n[j - 1]
373    movq    %rdx,%r15                   // r15 = hi(a[j - 1] * b[0])
374
375    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j - 1]
376    ADD_CARRY    %rax,%rdi              // rdi = hi(t[0] * k0 * n[j - 2]) + lo(t[0] * k0 * n[j - 1])
377    ADD_CARRY    %r14,%rdi              // rdi +=  hi(a[j - 2] * b[0]) + lo(a[j- 1] * b[0])
378    movq    %rdi,-16(%rsp,%r10,8)       // t[j - 2] = rdi
379    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j - 1])
380
381    xorq    %rdx,%rdx                   // rdx = 0
382    ADD_CARRY    %r15,%r12              // r12 = hi(a[j - 1] * b[0]) + hi(t[0] * k0 * n[j - 1])
383    movq    %r12,-8(%rsp,%r10,8)        // t[j - 1] = r13
384    movq    %rdx,(%rsp,%r10,8)          // t[j] = CF
385
386    leaq    1(%r11),%r11                // i++
387.align  4
388.LoopOuter4x:
389    /* Calculate a[i] * b + q * N */
390    movq    (%rsi),%rax                 // rax = a[0]
391    movq    (%r13,%r11,8),%rbx          // rbx = b[i]
392    xorq    %r10,%r10                   // j = 0
393    movq    (%rsp),%r15                 // r15 = t[0]
394    movq    %r8,%rbp                    // rbp = k0
395    mulq    %rbx                        // (rdx, rax) = a[0] * b[i]
396    ADD_CARRY    %rax,%r15              // r15 = lo(a[0] * b[i]) + t[0]
397    movq    (%rcx),%rax                 // rax = n[0]
398
399    imulq   %r15,%rbp                   // rbp = t[0] * k0
400    movq    %rdx,%r14                   // r14 = hi[a[0] * b[i]]
401
402    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[0]
403    ADD_CARRY    %rax,%r15              // r15 = lo(t[0] * k0 * n[0])
404    movq    8(%rsi),%rax                // rax = a[1]
405    movq    %rdx,%rdi                   // rdi = hi(t[0] * k0 * n[0])
406
407    mulq    %rbx                        // (rdx, rax) = a[1] * b[i]
408    ADD_CARRY    %rax,%r14              // r14 = hi[a[0] * b[i]] + lo(a[1] * b[i])
409    movq    8(%rcx),%rax                // rax = n[1]
410    ADD_CARRY    8(%rsp),%r14           // r14 = t[1]
411    movq    %rdx,%r15                   // r15 = hi(a[1] * b[i])
412
413    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[1]
414    ADD_CARRY    %rax,%rdi              // rdi = hi(t[0] * k0 * n[0]) + lo(t[0] * k0 * n[1])
415    movq    16(%rsi),%rax               // rax = a[2]
416    ADD_CARRY    %r14,%rdi              // rdi += t[1]
417    leaq    4(%r10),%r10                // j += 4
418    movq    %rdi,(%rsp)                 // t[0] = rdi
419    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[1])
420
421.align  16
422.Linner4x:
423    mulq    %rbx                        // (rdx, rax) = a[2] * b[i]
424    ADD_CARRY    %rax,%r15              // r15 = hi(a[1] * b[i]) + lo(a[2] * b[i])
425    addq    -16(%rsp,%r10,8),%r15       // r15 = t[j - 2]
426    adcq    $0,%rdx
427
428    movq    -16(%rcx,%r10,8),%rax       // rax = n[j - 2]
429    movq    %rdx,%r14                   // r14 = hi(a[2] * b[i])
430    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j - 2]
431    ADD_CARRY    %rax,%r12              // r12 = hi(t[0] * k0 * n[j - 3]) * lo(t[0] * k0 * n[j - 2])
432    ADD_CARRY    %r15,%r12              // r12 += t[j - 2]
433    movq    %r12,-24(%rsp,%r10,8)       // t[j - 3] = r13
434    movq    %rdx,%rdi                   // rdi = hi(t[0] * k0 * n[j - 2])
435
436    movq    -8(%rsi,%r10,8),%rax        // rax = a[j - 1]
437    mulq    %rbx                        // (rdx, rax) = a[j - 1] * b[i]
438    ADD_CARRY    %rax,%r14              // r14 = lo(a[j - 1] * b[i])
439    addq    -8(%rsp,%r10,8),%r14        // r14 += t[j - 1]
440    adcq    $0,%rdx
441    movq    %rdx,%r15                   // r15 = hi(a[j - 1] * b[i])
442
443    movq    -8(%rcx,%r10,8),%rax        // rax = n[j - 1]
444    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j - 1]
445    ADD_CARRY    %rax,%rdi              // rdi = hi(t[0] * k0 * n[j - 2]) + lo(t[0] * k0 * n[j - 1])
446    ADD_CARRY    %r14,%rdi              // rdi += t[j - 1]
447    movq    %rdi,-16(%rsp,%r10,8)       // t[j - 2] = rdi
448    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j - 1])
449
450    movq    (%rsi,%r10,8),%rax          // rax = a[j]
451    mulq    %rbx                        // (rdx, rax) = a[j] * b[i]
452    ADD_CARRY    %rax,%r15              // r15 = hi(a[j - 1] * b[i]) + lo(a[j] * b[i])
453    addq    (%rsp,%r10,8),%r15          // r15 = t[j]
454    adcq    $0,%rdx
455    movq    %rdx,%r14                   // r14 = hi(a[j] * b[i])
456
457    movq    (%rcx,%r10,8),%rax          // rax = n[j]
458    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j]
459    ADD_CARRY    %rax,%r12              // r12 = hi(t[0] * k0 * n[j - 1]) + lo(t[0] * k0 * n[j])
460    ADD_CARRY    %r15,%r12              // r12 += t[j]
461    movq    %r12,-8(%rsp,%r10,8)        // t[j - 1] = r13
462    movq    %rdx,%rdi                   // rdi = hi(t[0] * k0 * n[j])
463
464    movq    8(%rsi,%r10,8),%rax         // rax = a[j + 1]
465    mulq    %rbx                        // (rdx, rax) = a[j + 1] * b[i]
466    ADD_CARRY    %rax,%r14              // r14 = hi(a[j] * b[i]) + lo(a[j + 1] * b[i])
467    addq    8(%rsp,%r10,8),%r14         // r14 = t[j + 1]
468    adcq    $0,%rdx
469    movq    %rdx,%r15                   // r15 = hi(a[j + 1] * b[i])
470
471    movq    8(%rcx,%r10,8),%rax         // rax = n[j + 1]
472    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j + 1]
473    ADD_CARRY    %rax,%rdi              // rdi = hi(t[0] * k0 * n[j]) + lo(t[0] * k0 * n[j + 1])
474    ADD_CARRY    %r14,%rdi              // rdi += t[j + 1]
475    movq    %rdi,(%rsp,%r10,8)          // t[j] = rdi
476    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j + 1])
477    movq    16(%rsi,%r10,8),%rax        // rax = a[j + 2]
478
479    leaq    4(%r10),%r10                // j += 4
480    cmpq    %r9,%r10                    // if j != size
481    jb      .Linner4x
482
483    mulq    %rbx                        // (rdx, rax) = a[j - 2] * b[i]
484    ADD_CARRY    %rax,%r15              // r15 = hi(a[j + 1] * b[i]) + lo(a[j - 2] * b[i])
485    addq    -16(%rsp,%r10,8),%r15       // r15 = t[j - 2]
486    adcq    $0,%rdx
487    movq    %rdx,%r14                   // r14 = hi(a[j - 2] * b[i])
488
489    movq    -16(%rcx,%r10,8),%rax       // rax = n[j - 2]
490    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j - 2]
491    ADD_CARRY    %rax,%r12              // r12 = hi(t[0] * k0 * n[j + 1]) + lo(t[0] * k0 * n[j - 2])
492    ADD_CARRY    %r15,%r12              // r12 += t[j - 2]
493    movq    %r12,-24(%rsp,%r10,8)       // t[j - 3] = r13
494    movq    %rdx,%rdi                   // rdi = hi(t[0] * k0 * n[j - 2])
495
496    movq    -8(%rsi,%r10,8),%rax        // rax = a[j - 1]
497    mulq    %rbx                        // (rdx, rax) = a[j - 1] * b[i]
498    ADD_CARRY    %rax,%r14              // r14 = hi(a[j - 2] * b[i]) + lo(a[j - 1] * b[i])
499    addq    -8(%rsp,%r10,8),%r14        // r14 = t[j - 1]
500    adcq    $0,%rdx
501    leaq    1(%r11),%r11                // i++
502    movq    %rdx,%r15                   // r15 = hi(a[j - 1] * b[i])
503
504    movq    -8(%rcx,%r10,8),%rax        // rax = n[j - 1]
505    mulq    %rbp                        // (rdx, rax) = t[0] * k0 * n[j - 1]
506    ADD_CARRY    %rax,%rdi              // rdi = hi(t[0] * k0 * n[j - 2]) + lo(t[0] * k0 * n[j - 1])
507    ADD_CARRY    %r14,%rdi              // rdi += t[j - 1]
508    movq    %rdi,-16(%rsp,%r10,8)       // t[j - 2] = rdi
509    movq    %rdx,%r12                   // r12 = hi(t[0] * k0 * n[j - 1])
510
511    xorq    %rdx,%rdx                   // rdi = 0
512    ADD_CARRY    %r15,%r12              // r12 = hi(t[0] * k0 * n[j - 1]) + r10
513    addq    (%rsp,%r9,8),%r12           // r12 += t[size]
514    adcq    $0,%rdx
515    movq    %r12,-8(%rsp,%r10,8)        // t[j - 1] = r13
516    movq    %rdx,(%rsp,%r10,8)          // t[j] = CF
517
518    cmpq    %r9,%r11                    // if i != size
519    jb      .LoopOuter4x
520
521    movq    16(%rsp,%r9,8),%rdi         // rdi = t[size + 2]
522    leaq    -4(%r9),%r10                // j = size - 4
523    movq    (%rsp),%rax                 // rax = t[0]
524    movq    8(%rsp),%rdx                // rdx = t[1]
525    shrq    $2,%r10                     // r10 = (size - 4) / 4
526    leaq    (%rsp),%rsi                 // rsi = t[0]
527    xorq    %r11,%r11                   // i = 0
528
529    subq    (%rcx),%rax                 // rax = t[0] - n[0]
530    sbbq    8(%rcx),%rdx                // rdx = t[1] - (n[1] + CF)
531    movq    16(%rsi),%rbx               // rbx = t[2]
532    movq    24(%rsi),%rbp               // rbp = t[3]
533
534    /* 计算 S-N */
535.LoopSub4x:
536    movq    %rax,(%rdi,%r11,8)          // r[i] = n[0]
537    movq    %rdx,8(%rdi,%r11,8)         // r[i + 1] = n[1]
538
539    movq    32(%rsi,%r11,8),%rax        // rax = t[i + 4]
540    movq    40(%rsi,%r11,8),%rdx        // rdx = t[i + 5]
541
542    sbbq    16(%rcx,%r11,8),%rbx        // rbx = t[2] - (n[i + 2] + CF)
543    sbbq    24(%rcx,%r11,8),%rbp        // rbp = t[3] - (n[i + 3] + CF)
544    sbbq    32(%rcx,%r11,8),%rax        // rax = t[i + 4] - (n[j + 4] + CF)
545    sbbq    40(%rcx,%r11,8),%rdx        // rdx = t[i + 5] - (n[i + 5] + CF)
546
547    movq    %rbx,16(%rdi,%r11,8)        // r[i + 2] = rbx
548    movq    %rbp,24(%rdi,%r11,8)        // r[i + 3] = rbp
549
550    movq    48(%rsi,%r11,8),%rbx        // rbx = t[i + 6]
551    movq    56(%rsi,%r11,8),%rbp        // rbp = t[i + 7]
552    leaq    4(%r11),%r11                // i += 4
553    decq    %r10                        // j--
554    jnz     .LoopSub4x                  // if j != 0
555
556    sbbq    16(%rcx,%r11,8),%rbx        // rbx = rbx = t[i + 6] - (n[i + 2] + CF)
557    sbbq    24(%rcx,%r11,8),%rbp        // rbp = t[i + 7] - (n[i + 3] + CF)
558
559    movq    %rax,(%rdi,%r11,8)          // r[i] = rax
560    movq    %rdx,8(%rdi,%r11,8)         // r[i + 1] = rdx
561    movq    %rbx,16(%rdi,%r11,8)        // r[i + 2] = rbx
562    movq    %rbp,24(%rdi,%r11,8)        // r[i + 3] = rbp
563
564    movq    32(%rsi,%r11,8),%rax        // rax = t[i + 4]
565    sbbq    $0,%rax                     // rax -= CF
566
567    pxor    %xmm2,%xmm2                 // xmm0 = 0
568    movq    %rax, %xmm0
569    pcmpeqd %xmm1,%xmm1                 // xmm5 = -1
570    pshufd  $0,%xmm0,%xmm0
571    movq    %r9,%r10                    // j = size
572    pxor    %xmm0,%xmm1
573    shrq    $2,%r10                     // j = size / 4
574    xorl    %eax,%eax                   // i = 0
575
576.align  16
577.LoopCopy4x:
578
579    movdqa  (%rsp,%rax),%xmm5         // Copy the result to r.
580    movdqu  (%rdi,%rax),%xmm3
581    pand    %xmm0,%xmm5
582    pand    %xmm1,%xmm3
583    movdqa  16(%rsp,%rax),%xmm4
584    movdqa  %xmm2,(%rsp,%rax)
585    por     %xmm3,%xmm5
586    movdqu  16(%rdi,%rax),%xmm3
587    movdqu  %xmm5,(%rdi,%rax)
588    pand    %xmm0,%xmm4
589    pand    %xmm1,%xmm3
590    movdqa  %xmm2,16(%rsp,%rax)
591    por     %xmm3,%xmm4
592    movdqu  %xmm4,16(%rdi,%rax)
593    leaq    32(%rax),%rax
594    decq    %r10                        // j--
595    jnz     .LoopCopy4x
596    movq    8(%rsp,%r9,8),%rsi          // rsi = pressed-stacked rsp.
597    movq    $1,%rax
598    leaq    (%rsi),%rsp                 // Restore srsp.
599    RESTORE_REGISTERS
600    ret
601.cfi_endproc
602.size   MontMul4,.-MontMul4
603
604.type   MontSqr8,@function
605.align  32
606MontSqr8:
607.cfi_startproc
608    SAVE_REGISTERS
609    movq    %rsp,%rax
610
611    movl    %r9d,%r15d
612    shll    $3,%r9d                 // Calculate size * 8 bytes.
613    shlq    $5,%r15                 // size * 8 * 4
614    negq    %r9
615
616    leaq    -64(%rsp,%r9,2),%r14    // r14 = rsp[size * 2 - 8]
617    subq    %rsi,%r14
618    andq    $4095,%r14
619    movq    %rsp,%rbp
620    cmpq    %r14,%r15
621    jae     .Loop8xCheckstk
622
623    leaq    4032(,%r9,2),%r15    // r15 = 4096 - frame - 2 * size
624    subq    %r15,%r14
625    movq    $0,%r15
626    cmovcq  %r15,%r14
627
628.Loop8xCheckstk:
629    subq    %r14,%rbp
630    leaq    -64(%rbp,%r9,2),%rbp    // Allocate a frame + 2 x size.
631
632    andq    $-64,%rbp               // __checkstk implementation,
633                                    // which is invoked when the stack size needs to exceed one page.
634    movq    %rsp,%r14
635    subq    %rbp,%r14
636    andq    $-4096,%r14
637    leaq    (%r14,%rbp),%rsp
638    cmpq    %rbp,%rsp
639    jbe     .LoopMul8x
640
641.align  16
642.LoopPage8x:
643    leaq    -4096(%rsp),%rsp        // Change sp - 4096 each time until sp <= the space to be allocated
644    cmpq    %rbp,%rsp
645    ja      .LoopPage8x
646
647.LoopMul8x:
648    movq    %r9,%r15                // r15 = -size * 8
649    negq    %r9                     // Restoresize.
650    movq    %r8,32(%rsp)            // Save the values of k0 and sp.
651    movq    %rax,40(%rsp)
652
653    movq    %rcx, %xmm1             // Pointer to saving n.
654    pxor    %xmm2,%xmm2             // xmm0 = 0
655    movq    %rdi, %xmm0             // Pointer to saving r.
656    movq    %r15, %xmm5             // Save size.
657    call    MontSqr8Inner
658
659    leaq    (%rdi,%r9),%rbx       // rbx = t[size]
660    movq    %r9,%rcx                // rcx = -size
661    movq    %r9,%rdx                // rdx = -size
662    movq    %xmm0, %rdi             // rdi = r
663    sarq    $5,%rcx               // rcx >>= 5
664
665.align  32
666/* T -= N */
667.LoopSub8x:
668    movq    (%rbx),%r13             // r13 = t[i]
669    movq    8(%rbx),%r12            // r12 = t[i + 1]
670    movq    16(%rbx),%r11           // r11 = t[i + 2]
671    movq    24(%rbx),%r10           // r10 = t[i + 3]
672
673    sbbq    (%rbp),%r13             // r13 = t[i] - (n[i] + CF)
674    sbbq    8(%rbp),%r12            // r12 = t[i + 1] - (n[i + 1] + CF)
675    sbbq    16(%rbp),%r11           // r11 = t[i + 2] - (n[i + 2] + CF)
676    sbbq    24(%rbp),%r10           // r10 = t[i + 3] - (n[i + 3] + CF)
677
678    movq    %r13,0(%rdi)            // Assigning value to r.
679    movq    %r12,8(%rdi)
680    movq    %r11,16(%rdi)
681    movq    %r10,24(%rdi)
682
683    leaq    32(%rbp),%rbp           // n += 4
684    leaq    32(%rdi),%rdi           // r += 4
685    leaq    32(%rbx),%rbx           // t += 4
686    incq    %rcx
687    jnz     .LoopSub8x
688
689    sbbq    $0,%rax                 // rax -= CF
690    leaq    (%rbx,%r9),%rbx
691    leaq    (%rdi,%r9),%rdi
692
693    movq    %rax,%xmm0
694    pxor    %xmm2,%xmm2
695    pshufd  $0,%xmm0,%xmm0
696    movq    40(%rsp),%rsi           // rsi = pressed-stacked rsp.
697
698.align  32
699.LoopCopy8x:
700    movdqa  0(%rbx),%xmm1           // Copy the result to r.
701    movdqa  16(%rbx),%xmm5
702    leaq    32(%rbx),%rbx
703    movdqu  0(%rdi),%xmm3
704    movdqu  16(%rdi),%xmm4
705    leaq    32(%rdi),%rdi
706    movdqa  %xmm2,-32(%rbx)
707    movdqa  %xmm2,-16(%rbx)
708    movdqa  %xmm2,-32(%rbx,%rdx)
709    movdqa  %xmm2,-16(%rbx,%rdx)
710    pcmpeqd %xmm0,%xmm2
711    pand    %xmm0,%xmm1
712    pand    %xmm0,%xmm5
713    pand    %xmm2,%xmm3
714    pand    %xmm2,%xmm4
715    pxor    %xmm2,%xmm2
716    por     %xmm1,%xmm3
717    por     %xmm5,%xmm4
718    movdqu  %xmm3,-32(%rdi)
719    movdqu  %xmm4,-16(%rdi)
720    addq    $32,%r9
721    jnz     .LoopCopy8x
722
723    movq    $1,%rax
724    leaq    (%rsi),%rsp             // Restore rsp.
725    RESTORE_REGISTERS               // Restore non-volatile register.
726    ret
727.cfi_endproc
728.size   MontSqr8,.-MontSqr8
729
730.type   MontSqr8Inner,@function
731.align  32
732MontSqr8Inner:
733.cfi_startproc
734    leaq    32(%r15),%rbp           // i = -size + 32
735    leaq    (%rsi,%r9),%rsi       // rsi = a[size]
736    movq    %r9,%rcx                // j = size
737
738    movq    -32(%rsi,%rbp),%r11   // r11 = a[0]
739    movq    -24(%rsi,%rbp),%r10   // r10 = a[1]
740
741    leaq    56(%rsp,%r9,2),%rdi   // rdi = t[2 * size]
742    leaq    -16(%rsi,%rbp),%rbx   // rbx = a[2]
743    leaq    -32(%rdi,%rbp),%rdi   // rdi = t[2 * size - i]
744
745    movq    %r10,%rax               // rax = a[1]
746    mulq    %r11                    // (rdx, rax) = a[1] * a[0]
747    movq    %rax,%r15               // r15 = lo(a[1] * a[0])
748    movq    %rdx,%r14               // r14 = hi(a[1] * a[0])
749    movq    %r15,-24(%rdi,%rbp)   // t[1] = lo(a[1] * a[0])
750
751    movq    (%rbx),%rax             // rax = a[2]
752    mulq    %r11                    // (rdx, rax) = a[2] * a[0]
753    ADD_CARRY    %rax,%r14          // r14 = hi(a[1] * a[0]) + lo(a[2] * a[0])
754    movq    %r14,-16(%rdi,%rbp)   // t[2] = hi(a[1] * a[0]) + lo(a[2] * a[0])
755    movq    %rdx,%r15               // r15 = hi(a[2] * a[0])
756
757    movq    (%rbx),%rax             // rax = a[2]
758    mulq    %r10                    // (rdx, rax) = a[2] * a[1]
759    movq    %rax,%r13               // r13 = lo(a[2] * a[1])
760    movq    %rdx,%r12               // r12 = hi(a[2] * a[1])
761
762    leaq    8(%rbx),%rbx            // rbx = a[3]
763    movq    (%rbx),%rax             // rax = a[3]
764    mulq    %r11                    // (rdx, rax) = a[3] * a[0]
765    ADD_CARRY    %rax,%r15          // r15 = hi(a[2] * a[0]) + lo(a[3] * a[0])
766    ADD_CARRY    %r13,%r15          // r15 = hi(a[2] * a[0]) + lo(a[3] * a[0]) + lo(a[2] * a[1])
767    movq    %rdx,%r14               // r14 = hi(a[3] * a[0])
768
769    movq    (%rbx),%rax             // rax = a[3]
770    leaq    (%rbp),%rcx             // j = i
771    movq    %r15,-8(%rdi,%rcx)      // t[3] = hi(a[2] * a[0]) + lo(a[3] * a[0]) + lo(a[2] * a[1])
772
773.align  32
774.Loop1stSqr4x:
775    leaq    (%rsi,%rcx),%rbx        // rbx = a[4]
776    mulq    %r10                    // (rdx, rax) = a[3] * a[1]
777    ADD_CARRY    %rax,%r12          // r12 = hi(a[2] * a[1]) + lo(a[3] * a[1])
778    movq    %rdx,%r13               // r13 = hi(a[3] * a[1])
779
780    movq    (%rbx),%rax             // rax = a[4]
781    mulq    %r11                    // (rdx, rax) = a[4] * a[0]
782    ADD_CARRY    %rax,%r14          // r14 = hi(a[3] * a[0]) + lo(a[4] * a[0])
783    ADD_CARRY    %r12,%r14          // r14 = hi(a[3] * a[0]) + lo(a[4] * a[0]) + lo(a[3] * a[1])
784
785    movq    (%rbx),%rax             // rax = a[4]
786    movq    %rdx,%r15               // r15 = hi(a[4] * a[0])
787    mulq    %r10                    // (rdx, rax) = a[4] * a[1]
788    ADD_CARRY    %rax,%r13          // r13 = hi(a[3] * a[1]) + lo(a[4] * a[1])
789    movq    %r14,(%rdi,%rcx)        // t[4] = hi(a[3] * a[0]) + lo(a[4] * a[0]) + lo(a[3] * a[1])
790    movq    %rdx,%r12               // r12 = hi(a[4] * a[1])
791
792    leaq    8(%rbx),%rbx            // rbx = a[5]
793    movq    (%rbx),%rax             // rax = a[5]
794    mulq    %r11                    // (rdx, rax) = a[5] * a[0]
795    ADD_CARRY    %rax,%r15          // r15 = hi(a[4] * a[0]) + lo(a[5] * a[0])
796    ADD_CARRY    %r13,%r15          // r15 = hi(a[4] * a[0]) + lo(a[5] * a[0]) + hi(a[3] * a[1]) + lo(a[4] * a[1])
797
798    movq    (%rbx),%rax             // rax = a[5]
799    movq    %rdx,%r14               // r14 = hi(a[5] * a[0])
800    mulq    %r10                    // (rdx, rax) = a[5] * a[1]
801    ADD_CARRY    %rax,%r12          // r12 = hi(a[4] * a[1]) + lo(a[5] * a[1])
802    movq    %r15,8(%rdi,%rcx)       // t[5] = r10
803    movq    %rdx,%r13               // r13 = hi(a[5] * a[1])
804
805    leaq    8(%rbx),%rbx            // rbx = a[6]
806    movq    (%rbx),%rax             // rax = a[6]
807    mulq    %r11                    // (rdx, rax) = a[6] * a[0]
808    ADD_CARRY    %rax,%r14          // r14 = hi(a[5] * a[0]) + lo(a[6] * a[0])
809    ADD_CARRY    %r12,%r14          // r14 = hi(a[5] * a[0]) + lo(a[6] * a[0]) + hi(a[4] * a[1]) + lo(a[5] * a[1])
810
811    movq    (%rbx),%rax             // rax = a[6]
812    movq    %rdx,%r15               // r15 = hi(a[6] * a[0])
813    mulq    %r10                    // (rdx, rax) = a[6] * a[1]
814    ADD_CARRY    %rax,%r13          // r13 = lo(a[6] * a[1])
815    movq    %r14,16(%rdi,%rcx)      // t[6] = r11
816    movq    %rdx,%r12               // r12 = hi(a[6] * a[1])
817
818    leaq    8(%rbx),%rbx            // rbx = a[7]
819    movq    (%rbx),%rax             // rax = a[7]
820    mulq    %r11                    // (rdx, rax) = a[7] * a[0]
821    ADD_CARRY    %rax,%r15          // r15 = hi(a[6] * a[0]) + lo(a[7] * a[0])
822    ADD_CARRY    %r13,%r15          // r15 = hi(a[6] * a[0]) + lo(a[7] * a[0]) + lo(a[6] * a[1])
823    movq    %r15,24(%rdi,%rcx)    // t[7] = hi(a[6] * a[0]) + lo(a[7] * a[0]) + lo(a[6] * a[1])
824    movq    %rdx,%r14               // r14 = hi(a[7] * a[0])
825
826    movq    (%rbx),%rax             // rax = a[7]
827    leaq    32(%rcx),%rcx           // j += 2
828    cmpq    $0,%rcx                 // if j != 0
829    jne     .Loop1stSqr4x
830
831    mulq    %r10                    // (rdx, rax) = a[7] * a[1]
832    ADD_CARRY    %rax,%r12          // r12 = hi(a[6] * a[1]) + lo(a[7] * a[1])
833    leaq    16(%rbp),%rbp           // i++
834    ADD_CARRY    %r14,%r12          // r12 = hi(a[6] * a[1]) + hi(a[7] * a[0]) + lo(a[7] * a[1])
835
836    movq    %r12,(%rdi)             // t[8] = r13
837    movq    %rdx,%r13               // r13 = hi(a[7] * a[1])
838    movq    %rdx,8(%rdi)            // t[9] = hi(a[7] * a[1])
839
840.align  32
841.LoopOuterSqr4x:
842    movq    -32(%rsi,%rbp),%r11   // r11 = a[0]
843    movq    -24(%rsi,%rbp),%r10   // r10 = a[1]
844
845    leaq    -16(%rsi,%rbp),%rbx   // rbx = a[2]
846    leaq    56(%rsp,%r9,2),%rdi   // rdi = t[size * 2 - i]
847    leaq    -32(%rdi,%rbp),%rdi
848
849    movq    %r10,%rax               // rax = a[1]
850    mulq    %r11                    // (rdx, rax) =  a[1] * a[0]
851    movq    -24(%rdi,%rbp),%r15     // r15 = t[1]
852    ADD_CARRY    %rax,%r15          // r15 = lo(a[1] * a[0]) + t[1]
853    movq    %r15,-24(%rdi,%rbp)     // t[1] = r10
854    movq    %rdx,%r14               // r14 = hi(a[1] * a[0])
855
856    movq    (%rbx),%rax             // rax = a[2]
857    mulq    %r11                    // (rdx, rax) = a[2] * a[0]
858    ADD_CARRY    %rax,%r14          // r14 = hi(a[1] * a[0]) + lo(a[2] * a[0])
859    addq    -16(%rdi,%rbp),%r14     // r14 = hi(a[1] * a[0]) + lo(a[2] * a[0]) + t[2]
860    adcq    $0,%rdx                 // r10 += CF
861    movq    %rdx,%r15               // r10 = hi(a[2] * a[0])
862    movq    %r14,-16(%rdi,%rbp)     // t[2] = r11
863
864    xorq    %r13,%r13               // Clear CF.
865
866    movq    (%rbx),%rax             // rax = a[2]
867    mulq    %r10                    // (rdx, rax) = a[2] * a[1]
868    ADD_CARRY    %rax,%r13          // r13 = lo(a[2] * a[1])
869    addq    -8(%rdi,%rbp),%r13      // r13 = lo(a[2] * a[1]) + t[3]
870    adcq    $0,%rdx
871    movq    %rdx,%r12               // r12 = hi(a[2] * a[1])
872
873    leaq    8(%rbx),%rbx            // rbx = a[3]
874    movq    (%rbx),%rax             // rax = a[3]
875    mulq    %r11                    // (rdx, rax) = a[3] * a[0]
876    ADD_CARRY    %rax,%r15          // r15 = hi(a[2] * a[0]) + lo(a[3] * a[0])
877    ADD_CARRY    %r13,%r15          // r15 = hi(a[2] * a[0]) + lo(a[3] * a[0]) + lo(a[2] * a[1]) + t[3]
878
879    movq    (%rbx),%rax             // rax = a[3]
880    leaq    (%rbp),%rcx             // j = i
881    movq    %r15,-8(%rdi,%rbp)      // t[3] = r10
882    movq    %rdx,%r14               // r14 = hi(a[3] * a[0])
883
884.align  32
885.LoopInnerSqr4x:
886    leaq    (%rsi,%rcx),%rbx        // rbx = a[4]
887    mulq    %r10                    // (rdx, rax) = a[3] * a[1]
888    ADD_CARRY    %rax,%r12          // r12 = hi(a[2] * a[1]) + lo(a[3] * a[1])
889    movq    (%rbx),%rax             // rax = a[4]
890    movq    %rdx,%r13               // r13 = hi(a[3] * a[1])
891    addq    (%rdi,%rcx),%r12        // r12 = hi(a[2] * a[1]) + lo(a[3] * a[1]) + t[4]
892    adcq    $0,%rdx                 // r13 += CF
893    movq    %rdx,%r13               // r13 = hi(a[3] * a[1])
894
895    mulq    %r11                    // (rdx, rax) = a[4] * a[0]
896    ADD_CARRY    %rax,%r14          // r14 = hi(a[3] * a[0]) + lo(a[4] * a[0])
897    ADD_CARRY    %r12,%r14          // r14 = hi(a[3] * a[0]) + lo(a[4] * a[0]) + hi(a[2] * a[1]) + lo(a[3] * a[1]) + t[4]
898    movq    %r14,(%rdi,%rcx)        // t[4] = r11
899    movq    %rdx,%r15               // r15 = hi(a[4] * a[0])
900
901    movq    (%rbx),%rax             // rax = a[4]
902    mulq    %r10                    // (rdx, rax) = a[4] * a[1]
903    ADD_CARRY    %rax,%r13          // r13 = hi(a[3] * a[1]) + lo(a[4] * a[1])
904    addq    8(%rdi,%rcx),%r13       // r13 = hi(a[3] * a[1]) + lo(a[4] * a[1]) + t[5]
905    adcq    $0,%rdx                 // r12 += CF
906
907    leaq    8(%rbx),%rbx            // rbx = a[5]
908    movq    (%rbx),%rax             // rax = a[5]
909    movq    %rdx,%r12               // r12 = hi(a[4] * a[1])
910    mulq    %r11                    // (rdx, rax) = a[5] * a[0]
911    ADD_CARRY    %rax,%r15          // r15 = hi(a[4] * a[0]) + lo(a[5] * a[0])
912    ADD_CARRY    %r13,%r15          // r15 = hi(a[4] * a[0]) + lo(a[5] * a[0]) + hi(a[3] * a[1]) + lo(a[4] * a[1]) + t[5]
913    movq    %r15,8(%rdi,%rcx)       // t[5] = r10
914    movq    %rdx,%r14               // r14 = hi(a[5] * a[0])
915
916    movq    (%rbx),%rax             // rax = a[5]
917    leaq    16(%rcx),%rcx           // j++
918    cmpq    $0,%rcx                 // if j != 0
919    jne     .LoopInnerSqr4x
920
921    mulq    %r10                    // (rdx, rax) = a[5] * a[1]
922    ADD_CARRY    %rax,%r12          // r12 = hi(a[4] * a[1]) + lo(a[5] * a[1])
923    ADD_CARRY    %r14,%r12          // r12 = hi(a[4] * a[1]) + lo(a[5] * a[1]) + hi(a[5] * a[0])
924
925    movq    %r12,(%rdi)             // t[6] = r13
926    movq    %rdx,%r13               // r13 = hi(a[5] * a[1])
927    movq    %rdx,8(%rdi)            // t[7] = hi(a[5] * a[1])
928
929    addq    $16,%rbp                // i++
930    jnz     .LoopOuterSqr4x         // if i != 0
931
932    movq    -32(%rsi),%r11          // r11 = a[0]
933    leaq    56(%rsp,%r9,2),%rdi   // rdi = t[2 * size]
934    movq    -24(%rsi),%rax          // rax = a[1]
935    leaq    -32(%rdi,%rbp),%rdi   // rdi = t[2 * size - i]
936    movq    -16(%rsi),%rbx          // rbx = a[2]
937    movq    %rax,%r10               // r10 = a[1]
938
939    mulq    %r11                    // (rdx, rax) = a[1] * a[0]
940    ADD_CARRY    %rax,%r15          // r15 = lo(a[1] * a[0]) + t[1]
941
942    movq    %rbx,%rax               // rax = a[2]
943    movq    %rdx,%r14               // r14 = hi(a[1] * a[0])
944    mulq    %r11                    // (rdx, rax) = a[2] * a[0]
945    ADD_CARRY    %rax,%r14          // r14 = hi(a[1] * a[0]) + lo(a[2] * a[0])
946    movq    %r15,-24(%rdi)          // t[1] = r10
947    ADD_CARRY    %r12,%r14          // r14 = lo(a[2] * a[0]) + t[2]
948
949    movq    %rbx,%rax               // rax = a[2]
950    movq    %rdx,%r15               // r15 = hi(a[2] * a[0])
951    mulq    %r10                    // (rdx, rax) = a[2] * a[1]
952    ADD_CARRY    %rax,%r13          // r13 = lo(a[2] * a[1]) + t[3]
953    movq    %r14,-16(%rdi)          // t[2] = r11
954    movq    %rdx,%r12               // r12 = hi(a[2] * a[1])
955
956    movq    -8(%rsi),%rbx           // rbx = a[3]
957    movq    %rbx,%rax               // rax = a[3]
958    mulq    %r11                    // (rdx, rax) = a[3] * a[0]
959    ADD_CARRY    %rax,%r15          // r15 = hi(a[2] * a[0]) + lo(a[3] * a[0])
960    ADD_CARRY    %r13,%r15          // r15 = hi(a[2] * a[0]) + lo(a[3] * a[0]) + lo(a[2] * a[1]) + t[3]
961
962    movq    %rbx,%rax               // rax = a[3]
963    movq    %r15,-8(%rdi)           // t[3] = r10
964    movq    %rdx,%r14               // r14 = hi(a[3] * a[0])
965    mulq    %r10                    // (rdx, rax) = a[3] * a[1]
966    ADD_CARRY    %rax,%r12          // r12 = hi(a[2] * a[1]) + lo(a[3] * a[1])
967    ADD_CARRY    %r14,%r12          // r12 = hi(a[3] * a[0]) + hi(a[2] * a[1]) + lo(a[3] * a[1])
968
969    movq    %r12,(%rdi)             // t[4] = r13
970    movq    %rdx,%r13               // r13 = hi(a[3] * a[1])
971    movq    %rdx,8(%rdi)            // t[5] = hi(a[3] * a[1])
972
973    movq    -16(%rsi),%rax          // rax = a[2]
974    mulq    %rbx                    // (rdx, rax) = a[3] * a[2]
975    addq    $16,%rbp
976    xorq    %r11,%r11
977    subq    %r9,%rbp                // i = 16 - size
978    xorq    %r10,%r10
979
980    ADD_CARRY    %r13,%rax          // rax = hi(a[3] * a[1]) + lo(a[3] * a[2])
981    movq    %rax,8(%rdi)            // t[5] = hi(a[3] * a[1]) + lo(a[3] * a[2])
982    movq    %rdx,16(%rdi)           // t[6] = hi(a[3] * a[2])
983    movq    %r10,24(%rdi)           // t[7] = 0
984
985    movq    -16(%rsi,%rbp),%rax   // rax = a[0]
986    leaq    56(%rsp),%rdi         // rdi = t[0]
987    xorq    %r15,%r15
988    movq    8(%rdi),%r14            // r14 = t[1]
989
990    leaq    (%r11,%r15,2),%r13
991    shrq    $63,%r15                // Cyclically shifts 63 bits to the right to obtain the lower bits.
992    leaq    (%rcx,%r14,2),%r12      // r12 = t[1] * 2
993    shrq    $63,%r14                // r14 = t[1] >> 63
994    orq     %r15,%r12               // r12 = t[1] * 2
995    movq    16(%rdi),%r15           // r15 = t[2]
996    movq    %r14,%r11               // r11 = t[1] >> 63
997    mulq    %rax                    // (rdx, rax) = a[0] * a[0]
998    negq    %r10                    // If the value is not 0, CF is set to 1.
999    adcq    %rax,%r13               // r13 = lo(a[0] * a[0])
1000    movq    24(%rdi),%r14           // r14 = t[3]
1001    movq    %r13,(%rdi)             // t[0] = 0
1002    adcq    %rdx,%r12               // r12 = t[1] * 2 + hi(a[0] * a[0])
1003
1004    leaq    (%r11,%r15,2),%rbx      // rbx = t[2] * 2 + t[1] >> 63
1005    movq    -8(%rsi,%rbp),%rax    // rax = a[1]
1006    movq    %r12,8(%rdi)            // t[1] = t[1] * 2 + hi(a[0] * a[0])
1007    sbbq    %r10,%r10               // r10 = -CF clear CF
1008    shrq    $63,%r15                // r15 = t[2] >> 63
1009    leaq    (%rcx,%r14,2),%r8       // r8 = t[3] * 2
1010    shrq    $63,%r14                // r14 = t[3] >> 63
1011    orq     %r15,%r8                // r8 = (t[3] * 2) + (t[2] >> 63)
1012    movq    32(%rdi),%r15           // r15 = t[4]
1013    movq    %r14,%r11               // r11 = t[3] >> 63
1014    mulq    %rax                    // (rdx, rax) = a[1] * a[1]
1015    negq    %r10                    // If the value is not 0, CF is set to 1.
1016    movq    40(%rdi),%r14           // r14 = t[5]
1017    adcq    %rax,%rbx               // rbx = t[2] * 2 + t[1] >> 63 + lo(a[1] * a[1])
1018    movq    (%rsi,%rbp),%rax     // rax = a[2]
1019    movq    %rbx,16(%rdi)           // t[2] = t[2] * 2 + t[1] >> 63 + lo(a[1] * a[1])
1020    adcq    %rdx,%r8                // r8 = t[3] * 2 + t[2] >> 63 + hi(a[1] * a[1])
1021    leaq    16(%rbp),%rbp           // i++
1022    movq    %r8,24(%rdi)            // t[3] = r8
1023    sbbq    %r10,%r10               // r10 = -CF clear CF.
1024    leaq    64(%rdi),%rdi           // t += 64
1025
1026.align  32
1027.LoopShiftAddSqr4x:
1028    leaq    (%r11,%r15,2),%r13      // r13 = t[4] * 2 + t[3] >> 63
1029    shrq    $63,%r15                // r15 = t[4] >> 63
1030    leaq    (%rcx,%r14,2),%r12      // r12 = t[5] * 2
1031    shrq    $63,%r14                // r14 = t[5] >> 63
1032    orq     %r15,%r12               // r12 = (t[5] * 2) + t[4] >> 63
1033    movq    -16(%rdi),%r15          // r15 = t[6]
1034    movq    %r14,%r11               // r11 = t[5] >> 63
1035    mulq    %rax                    // (rdx, rax) = a[2] * a[2]
1036    negq    %r10                    // r10 = CF
1037    movq    -8(%rdi),%r14           // r14 = t[7]
1038    adcq    %rax,%r13               // r13 = t[4] * 2 + t[3] >> 63 + lo(a[2] * a[2])
1039    movq    %r13,-32(%rdi)          // t[4] = r12
1040    adcq    %rdx,%r12               // r12 = (t[5] * 2) + t[4] >> 63 + hi(a[2] * a[2])
1041
1042    leaq    (%r11,%r15,2),%rbx      // rbx = t[6] * 2 + t[5] >> 63
1043    movq    -8(%rsi,%rbp),%rax    // rax = a[3]
1044    movq    %r12,-24(%rdi)          // t[5] = hi(a[2] * a[2])
1045    sbbq    %r10,%r10               // r10 = -CF
1046    shrq    $63,%r15                // r15 = t[6] >> 63
1047    leaq    (%rcx,%r14,2),%r8       // r8 = t[7] * 2
1048    shrq    $63,%r14                // r14 = t[7] >> 63
1049    orq     %r15,%r8                // r8 = t[7] * 2 + t[6] >> 63
1050    movq    0(%rdi),%r15            // r15 = t[8]
1051    movq    %r14,%r11               // r11 = t[7] >> 63
1052    mulq    %rax                    // (rdx, rax) = a[3] * a[3]
1053    negq    %r10                    // r10 = CF
1054    movq    8(%rdi),%r14            // r14 = t[9]
1055    adcq    %rax,%rbx               // rbx = t[6] * 2 + t[5] >> 63 + lo(a[3] * a[3])
1056    movq    %rbx,-16(%rdi)          // t[6] = rbx
1057    adcq    %rdx,%r8                // r8 = t[7] * 2 + t[6] >> 63 + hi(a[3] * a[3])
1058
1059    leaq    (%r11,%r15,2),%r13      // r13 = t[8] * 2 + t[7] >> 63
1060    movq    %r8,-8(%rdi)            // t[7] = hi(a[3] * a[3])
1061    movq    (%rsi,%rbp),%rax     // rax = a[4]
1062    sbbq    %r10,%r10               // r10 = -CF
1063    shrq    $63,%r15                // r15 = t[8] >> 63
1064    leaq    (%rcx,%r14,2),%r12      // r12 = t[9] * 2
1065    shrq    $63,%r14                // r14 = t[9] >> 63
1066    orq     %r15,%r12               // r12 = t[9] * 2 + t[8] >> 63
1067    movq    16(%rdi),%r15           // r15 = t[10]
1068    movq    %r14,%r11               // r11 = t[9] >> 63
1069    mulq    %rax                    // (rdx, rax) = a[4] * a[4]
1070    negq    %r10                    // r10 = -CF
1071    movq    24(%rdi),%r14           // r14 = t[11]
1072    adcq    %rax,%r13               // r13 = t[8] * 2 + t[7] >> 63 + lo(a[4] * a[4])
1073    movq    %r13,(%rdi)            // t[8] = r12
1074    adcq    %rdx,%r12               // r12 = t[9] * 2 + t[8] >> 63 + hi(a[4] * a[4])
1075
1076    leaq    (%r11,%r15,2),%rbx      // rbx = t[10] * 2 + t[9] >> 63
1077    movq    8(%rsi,%rbp),%rax     // rax = a[5]
1078    movq    %r12,8(%rdi)            // t[9] = r13
1079    sbbq    %r10,%r10               // r10 = -CF
1080    shrq    $63,%r15                // r15 = t[10] >> 63
1081    leaq    (%rcx,%r14,2),%r8       // r8 = t[11] * 2
1082    shrq    $63,%r14                // r14 = t[11] >> 63
1083    orq     %r15,%r8                // r8 = t[11] * 2 + t[10] >> 63
1084    movq    32(%rdi),%r15           // r15 = t[12]
1085    movq    %r14,%r11               // r11 = t[11] >> 63
1086    mulq    %rax                    // (rdx, rax) = a[5] * a[5]
1087    negq    %r10                    // r10 = CF
1088    movq    40(%rdi),%r14           // r14 = t[13]
1089    adcq    %rax,%rbx               // rbx = t[10] * 2 + t[9] >> 63 + lo(a[5] * a[5])
1090    movq    16(%rsi,%rbp),%rax    // rax = a[6]
1091    movq    %rbx,16(%rdi)           // t[10] = rbx
1092    adcq    %rdx,%r8                // r8 = t[11] * 2 + t[10] >> 63 + hi(a[5] * a[5])
1093    movq    %r8,24(%rdi)            // t[11] = r8
1094    sbbq    %r10,%r10               // r10 = -CF
1095    leaq    64(%rdi),%rdi           // t += 64
1096    addq    $32,%rbp                // i += 4
1097    jnz     .LoopShiftAddSqr4x          // if i != 0
1098
1099    leaq    (%r11,%r15,2),%r13      // r13 = t[12] * 2 + t[11] >> 63
1100    shrq    $63,%r15                // r15 = t[12] >> 63
1101    leaq    (%rcx,%r14,2),%r12      // r12 = t[13] * 2
1102    shrq    $63,%r14                // r14 = t[13] >> 63
1103    orq     %r15,%r12               // r12 = t[13] * 2 + t[12] >> 63
1104    movq    -16(%rdi),%r15          // r15 = t[14]
1105    movq    %r14,%r11               // r11 = t[13] >> 63
1106    mulq    %rax                    // (rdx, rax) = a[6] * a[6]
1107    negq    %r10                    // r10 = CF
1108    movq    -8(%rdi),%r14           // r14 = t[15]
1109    adcq    %rax,%r13               // r13 = t[12] * 2 + t[11] >> 63 + lo(a[6] * a[6])
1110    movq    %r13,-32(%rdi)          // t[12] = r12
1111    adcq    %rdx,%r12               // r12 = t[13] * 2 + t[12] >> 63 + hi(a[6] * a[6])
1112
1113    leaq    (%r11,%r15,2),%rbx      // rbx = t[14] * 2 + t[13] >> 63
1114    movq    -8(%rsi),%rax           // rax = a[7]
1115    movq    %r12,-24(%rdi)          // t[13] = r13
1116    sbbq    %r10,%r10               // r10 = -CF
1117    shrq    $63,%r15                // r15 = t[14] >> 63
1118    leaq    (%rcx,%r14,2),%r8       // r8 = t[15] * 2
1119    shrq    $63,%r14                // r14 = t[15] >> 63
1120    orq     %r15,%r8                // r8 = t[15] * 2 + t[14] >> 63
1121    mulq    %rax                    // (rdx, rax) = a[7] * a[7]
1122    negq    %r10                    // r10 = CF
1123    adcq    %rax,%rbx               // rbx = t[14] * 2 + t[13] >> 63 + lo(a[7] * a[7])
1124    adcq    %rdx,%r8                // r8 = t[15] * 2 + t[14] >> 63 + hi(a[7] * a[7])
1125    movq    %rbx,-16(%rdi)          // t[14] = rbx
1126    movq    %r8,-8(%rdi)            // t[15] = r8
1127
1128    movq    %xmm1,%rbp              // rbp = n
1129    xorq    %rax,%rax               // rax = 0
1130    leaq    (%r9,%rbp),%rcx       // rcx = n[size]
1131    leaq    56(%rsp,%r9,2),%rdx   // rdx = t[size * 2]
1132    movq    %rcx,8(%rsp)
1133    leaq    56(%rsp,%r9),%rdi
1134    movq    %rdx,16(%rsp)
1135    negq    %r9
1136
1137.align  32
1138.LoopReduceSqr8x:
1139    leaq    (%rdi,%r9),%rdi       // rdi = t[]
1140
1141    movq    (%rdi),%rbx            // rbx = t[0]
1142    movq    8(%rdi),%r9             // r9 = t[1]
1143    movq    16(%rdi),%r15           // r15 = t[2]
1144    movq    24(%rdi),%r14           // r14 = t[3]
1145    movq    32(%rdi),%r13           // r13 = t[4]
1146    movq    40(%rdi),%r12           // r12 = t[5]
1147    movq    48(%rdi),%r11           // r11 = t[6]
1148    movq    56(%rdi),%r10           // r10 = t[7]
1149    movq    %rax,(%rdx)             // Store the highest carry bit.
1150    leaq    64(%rdi),%rdi           // rdi = t[8]
1151
1152    movq    %rbx,%r8                // r8 = t[0]
1153    imulq   40(%rsp),%rbx         // rbx = k0 * t[0]
1154    movl    $8,%ecx
1155
1156.align  32
1157.LoopReduce8x:
1158    movq    (%rbp),%rax             // rax = n[0]
1159    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[0]
1160    negq    %r8                     // r8 = -t[0], If t[0] is not 0, set CF to 1.
1161    movq    %rdx,%r8                // r8 = hi(t[0] * k0 * n[0])
1162    adcq    $0,%r8                  // r8 += CF
1163
1164    movq    8(%rbp),%rax            // rax = n[1]
1165    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[1]
1166    movq    %rbx,48(%rsp,%rcx,8)
1167    ADD_CARRY    %rax,%r9           // r9 = t[1] + lo(t[0] * k0 * n[1])
1168    ADD_CARRY    %r9,%r8            // r8 = hi(t[0] * k0 * n[0]) + lo(t[0] * k0 * n[1]) + t[1]
1169
1170    movq    16(%rbp),%rax           // rax = n[2]
1171    movq    %rdx,%r9                // r9 = hi(t[0] * k0 * n[1])
1172    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[2]
1173    ADD_CARRY    %rax,%r15          // r15 = lo(t[0] * k0 * n[2]) + t[2]
1174    ADD_CARRY    %r15,%r9           // r9 = hi(t[0] * k0 * n[1]) + lo(t[0] * k0 * n[2]) + t[2]
1175    movq    40(%rsp),%rsi         // rsi = k0
1176    movq    %rdx,%r15               // r15 = hi(t[0] * k0 * n[2])
1177
1178    movq    24(%rbp),%rax           // rax = n[3]
1179    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[3]
1180    ADD_CARRY    %rax,%r14          // r14 = lo(t[0] * k0 * n[3])
1181    imulq   %r8,%rsi                // rsi = k0 * r8
1182    ADD_CARRY    %r14,%r15          // r15 = hi(t[0] * k0 * n[2]) + lo(t[0] * k0 * n[3])
1183    movq    %rdx,%r14               // r14 = hi(t[0] * k0 * n[3])
1184
1185    movq    32(%rbp),%rax           // rax = n[4]
1186    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[4]
1187    ADD_CARRY    %rax,%r13          // r13 = lo(t[0] * k0 * n[4]) + t[4]
1188    ADD_CARRY    %r13,%r14          // r14 = hi(t[0] * k0 * n[3]) + lo(t[0] * k0 * n[4]) + t[4]、
1189
1190    movq    40(%rbp),%rax           // rax = n[5]
1191    movq    %rdx,%r13               // r13 = hi(t[0] * k0 * n[4])
1192    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[5]
1193    ADD_CARRY    %rax,%r12          // r12 = lo(t[0] * k0 * n[5]) + t[5]
1194    ADD_CARRY    %r12,%r13          // r13 = hi(t[0] * k0 * n[4]) + lo(t[0] * k0 * n[5]) + t[5]
1195
1196    movq    48(%rbp),%rax           // rax = n[6]
1197    movq    %rdx,%r12               // r12 = hi(t[0] * k0 * n[5])
1198    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[6]
1199    ADD_CARRY    %rax,%r11          // r11 = lo(t[0] * k0 * n[6]) + t[6]
1200    ADD_CARRY    %r11,%r12          // r12 = hi(t[0] * k0 * n[5]) + lo(t[0] * k0 * n[6]) + t[6]
1201
1202    movq    56(%rbp),%rax           // rax = n[7]
1203    movq    %rdx,%r11               // r11 = hi(t[0] * k0 * n[6])
1204    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[7]
1205    movq    %rsi,%rbx               // rbx = k0 * r8
1206    ADD_CARRY    %rax,%r10          // r10 = lo(t[0] * k0 * n[7]) + t[7]
1207    ADD_CARRY    %r10,%r11          // r11 = hi(t[0] * k0 * n[6]) + lo(t[0] * k0 * n[7]) + t[7]
1208    movq    %rdx,%r10               // r10 = hi(t[0] * k0 * n[7])
1209
1210    decl    %ecx                    // ecx--
1211    jnz     .LoopReduce8x           // if ecx != 0
1212
1213    leaq    64(%rbp),%rbp           // rbp += 64, n Pointer Offset.
1214    xorq    %rax,%rax               // rax = 0
1215    movq    16(%rsp),%rdx           // rdx = t[size * 2]
1216    cmpq    8(%rsp),%rbp            // rbp = n[size]
1217    jae     .LoopEndCondMul8x
1218
1219    addq    (%rdi),%r8             // r8 += t[0]
1220    adcq    8(%rdi),%r9             // r9 += t[1]
1221    adcq    16(%rdi),%r15           // r15 += t[2]
1222    adcq    24(%rdi),%r14           // r14 += t[3]
1223    adcq    32(%rdi),%r13           // r13 += t[4]
1224    adcq    40(%rdi),%r12           // r12 += t[5]
1225    adcq    48(%rdi),%r11           // r11 += t[6]
1226    adcq    56(%rdi),%r10           // r10 += t[7]
1227    sbbq    %rsi,%rsi               // rsi = -CF
1228
1229    movq    112(%rsp),%rbx          // rbx = t[0] * k0, 48 + 56 + 8
1230    movl    $8,%ecx
1231
1232.align  32
1233.LoopLastSqr8x:
1234    movq    (%rbp),%rax            // rax = n[0]
1235    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[0]
1236    ADD_CARRY    %rax,%r8           // r8 += lo(t[0] * k0 * n[0])
1237    movq    %r8,(%rdi)              // t[0] = r8
1238    leaq    8(%rdi),%rdi            // t++
1239    movq    %rdx,%r8                // r8 = hi(t[0] * k0 * n[0])
1240
1241    movq    8(%rbp),%rax            // rax = n[1]
1242    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[1]
1243    ADD_CARRY    %rax,%r9           // r9 += lo(t[0] * k0 * n[1])
1244    ADD_CARRY    %r9,%r8            // r8 = hi(t[0] * k0 * n[0]) + r9
1245
1246    movq    16(%rbp),%rax           // rax = n[2]
1247    movq    %rdx,%r9                // r9 = hi(t[0] * k0 * n[1])
1248    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[2]
1249    ADD_CARRY    %rax,%r15          // r15 += lo(t[0] * k0 * n[2])
1250    ADD_CARRY    %r15,%r9           // r9 = hi(t[0] * k0 * n[1]) + r10
1251
1252    movq    24(%rbp),%rax           // rax = n[3]
1253    movq    %rdx,%r15               // r15 = hi(t[0] * k0 * n[2])
1254    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[3]
1255    ADD_CARRY    %rax,%r14          // r14 += lo(t[0] * k0 * n[3])
1256    ADD_CARRY    %r14,%r15          // r15 = hi(t[0] * k0 * n[2]) + r11
1257
1258    movq    32(%rbp),%rax           // rax = n[4]
1259    movq    %rdx,%r14               // r14 = hi(t[0] * k0 * n[3])
1260    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[4]
1261    ADD_CARRY    %rax,%r13          // r13 += lo(t[0] * k0 * n[4])
1262    ADD_CARRY    %r13,%r14          // r14 = hi(t[0] * k0 * n[3]) + r12
1263
1264    movq    40(%rbp),%rax           // rax = n[5]
1265    movq    %rdx,%r13               // r13 = hi(t[0] * k0 * n[4])
1266    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[5]
1267    ADD_CARRY    %rax,%r12          // r12 += lo(t[0] * k0 * n[5])
1268    ADD_CARRY    %r12,%r13          // r13 = hi(t[0] * k0 * n[4]) + r13
1269
1270    movq    48(%rbp),%rax           // rax = n[6]
1271    movq    %rdx,%r12               // r12 = hi(t[0] * k0 * n[5])
1272    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[6]
1273    ADD_CARRY    %rax,%r11          // r11 += lo(t[0] * k0 * n[6])
1274    ADD_CARRY    %r11,%r12          // r12 = hi(t[0] * k0 * n[5]) + r14
1275
1276    movq    56(%rbp),%rax           // rax = n[7]
1277    movq    %rdx,%r11               // r11 = hi(t[0] * k0 * n[6])
1278    mulq    %rbx                    // (rdx, rax) = t[0] * k0 * n[7]
1279    movq    40(%rsp,%rcx,8),%rbx    // rbx = t[i] * k0
1280    ADD_CARRY    %rax,%r10          // r10 += lo(t[0] * k0 * n[7])
1281    ADD_CARRY    %r10,%r11          // r11 = hi(t[0] * k0 * n[6]) + r10
1282    movq    %rdx,%r10               // r10 = hi(t[0] * k0 * n[7])
1283
1284    decl    %ecx                    // ecx--
1285    jnz     .LoopLastSqr8x              // if ecx != 0
1286
1287    leaq    64(%rbp),%rbp           // n += 8
1288    movq    16(%rsp),%rdx           // rdx = t[size * 2]
1289    cmpq    8(%rsp),%rbp            // Check whether rbp is at the end of the n array. If yes, exit the loop.
1290    jae     .LoopSqrBreak8x
1291
1292    movq    112(%rsp),%rbx          // rbx = t[0] * k0
1293    negq    %rsi                    // rsi = CF
1294    movq    (%rbp),%rax             // rax = = n[0]
1295    adcq    (%rdi),%r8              // r8 = t[0]
1296    adcq    8(%rdi),%r9             // r9 = t[1]
1297    adcq    16(%rdi),%r15           // r15 = t[2]
1298    adcq    24(%rdi),%r14           // r14 = t[3]
1299    adcq    32(%rdi),%r13           // r13 = t[4]
1300    adcq    40(%rdi),%r12           // r12 = t[5]
1301    adcq    48(%rdi),%r11           // r11 = t[6]
1302    adcq    56(%rdi),%r10           // r10 = t[7]
1303    sbbq    %rsi,%rsi               // rsi = -CF
1304
1305    movl    $8,%ecx                 // ecx = 8
1306    jmp     .LoopLastSqr8x
1307
1308.align  32
1309.LoopSqrBreak8x:
1310    xorq    %rax,%rax               // rax = 0
1311    addq    (%rdx),%r8              // r8 += Highest carry bit.
1312    adcq    $0,%r9                  // r9 += CF
1313    adcq    $0,%r15                 // r15 += CF
1314    adcq    $0,%r14                 // r14 += CF
1315    adcq    $0,%r13                 // r13 += CF
1316    adcq    $0,%r12                 // r12 += CF
1317    adcq    $0,%r11                 // r11 += CF
1318    adcq    $0,%r10                 // r10 += CF
1319    adcq    $0,%rax                 // rax += CF
1320
1321    negq    %rsi                    // rsi = CF
1322.LoopEndCondMul8x:
1323    adcq    (%rdi),%r8              // r8 += t[0]
1324    adcq    8(%rdi),%r9             // r9 += t[1]
1325    adcq    16(%rdi),%r15           // r15 += t[2]
1326    adcq    24(%rdi),%r14           // r14 += t[3]
1327    adcq    32(%rdi),%r13           // r13 += t[4]
1328    adcq    40(%rdi),%r12           // r12 += t[5]
1329    adcq    48(%rdi),%r11           // r11 += t[6]
1330    adcq    56(%rdi),%r10           // r10 += t[7]
1331    adcq    $0,%rax                 // rax += CF
1332    movq    -8(%rbp),%rcx           // rcx = n[7]
1333    xorq    %rsi,%rsi               // rsi = 0
1334
1335    movq    %xmm1,%rbp              // rbp = n
1336    movq    %r8,(%rdi)              // Save the calculated result back to t[].
1337    movq    %r9,8(%rdi)
1338    movq    %xmm5,%r9
1339    movq    %r15,16(%rdi)
1340    movq    %r14,24(%rdi)
1341    movq    %r13,32(%rdi)
1342    movq    %r12,40(%rdi)
1343    movq    %r11,48(%rdi)
1344    movq    %r10,56(%rdi)
1345    leaq    64(%rdi),%rdi           // t += 8
1346
1347    cmpq    %rdx,%rdi               // Cycle the entire t[].
1348    jb      .LoopReduceSqr8x
1349    ret
1350.cfi_endproc
1351.size   MontSqr8Inner,.-MontSqr8Inner
1352
1353#endif
1354