whitespace fix
[oweals/busybox.git] / networking / tls_pstm_sqr_comba.c
1 /*
2  * Copyright (C) 2017 Denys Vlasenko
3  *
4  * Licensed under GPLv2, see file LICENSE in this source tree.
5  */
6 #include "tls.h"
7
8 /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9  * Changes are flagged with //bbox
10  */
11
12 /**
13  *      @file    pstm_sqr_comba.c
14  *      @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15  *
16  *      Multiprecision Squaring with Comba technique.
17  */
18 /*
19  *      Copyright (c) 2013-2015 INSIDE Secure Corporation
20  *      Copyright (c) PeerSec Networks, 2002-2011
21  *      All Rights Reserved
22  *
23  *      The latest version of this code is available at http://www.matrixssl.org
24  *
25  *      This software is open source; you can redistribute it and/or modify
26  *      it under the terms of the GNU General Public License as published by
27  *      the Free Software Foundation; either version 2 of the License, or
28  *      (at your option) any later version.
29  *
30  *      This General Public License does NOT permit incorporating this software
31  *      into proprietary programs.  If you are unable to comply with the GPL, a
32  *      commercial license for this software may be purchased from INSIDE at
33  *      http://www.insidesecure.com/eng/Company/Locations
34  *
35  *      This program is distributed in WITHOUT ANY WARRANTY; without even the
36  *      implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37  *      See the GNU General Public License for more details.
38  *
39  *      You should have received a copy of the GNU General Public License
40  *      along with this program; if not, write to the Free Software
41  *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
42  *      http://www.gnu.org/copyleft/gpl.html
43  */
44 /******************************************************************************/
45
46 //bbox
47 //#include "../cryptoApi.h"
48 #ifndef DISABLE_PSTM
49
50 /******************************************************************************/
51 #if defined(PSTM_X86)
52 /* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
53 #if !defined(__GNUC__) || !defined(__i386__)
54 #error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
55 #endif
56 //#pragma message ("Using 32 bit x86 Assembly Optimizations")
57
58 #define COMBA_START
59
60 #define CLEAR_CARRY \
61    c0 = c1 = c2 = 0;
62
63 #define COMBA_STORE(x) \
64    x = c0;
65
66 #define COMBA_STORE2(x) \
67    x = c1;
68
69 #define CARRY_FORWARD \
70    do { c0 = c1; c1 = c2; c2 = 0; } while (0);
71
72 #define COMBA_FINI
73
74 #define SQRADD(i, j)                                      \
75 asm(                                            \
76          "movl  %6,%%eax     \n\t"                            \
77          "mull  %%eax        \n\t"                            \
78          "addl  %%eax,%0     \n\t"                            \
79          "adcl  %%edx,%1     \n\t"                            \
80          "adcl  $0,%2        \n\t"                            \
81          :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc");
82
83 #define SQRADD2(i, j)                                     \
84 asm(                                            \
85          "movl  %6,%%eax     \n\t"                            \
86          "mull  %7           \n\t"                            \
87          "addl  %%eax,%0     \n\t"                            \
88          "adcl  %%edx,%1     \n\t"                            \
89          "adcl  $0,%2        \n\t"                            \
90          "addl  %%eax,%0     \n\t"                            \
91          "adcl  %%edx,%1     \n\t"                            \
92          "adcl  $0,%2        \n\t"                            \
93          :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","%edx","%cc");
94
95 #define SQRADDSC(i, j)                                    \
96 asm(                                                     \
97          "movl  %6,%%eax     \n\t"                            \
98          "mull  %7           \n\t"                            \
99          "movl  %%eax,%0     \n\t"                            \
100          "movl  %%edx,%1     \n\t"                            \
101          "xorl  %2,%2        \n\t"                            \
102          :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc");
103
104 #define SQRADDAC(i, j)                                    \
105 asm(                                                     \
106          "movl  %6,%%eax     \n\t"                            \
107          "mull  %7           \n\t"                            \
108          "addl  %%eax,%0     \n\t"                            \
109          "adcl  %%edx,%1     \n\t"                            \
110          "adcl  $0,%2        \n\t"                            \
111          :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc");
112
113 #define SQRADDDB                                          \
114 asm(                                                     \
115          "addl %6,%0         \n\t"                            \
116          "adcl %7,%1         \n\t"                            \
117          "adcl %8,%2         \n\t"                            \
118          "addl %6,%0         \n\t"                            \
119          "adcl %7,%1         \n\t"                            \
120          "adcl %8,%2         \n\t"                            \
121          :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "%cc");
122
123 /******************************************************************************/
124 #elif defined(PSTM_X86_64)
125 /* x86-64 optimized */
126 #if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
127 #error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
128 #endif
129 //#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
130
131 #define COMBA_START
132
133 #define CLEAR_CARRY \
134 c0 = c1 = c2 = 0;
135
136 #define COMBA_STORE(x) \
137 x = c0;
138
139 #define COMBA_STORE2(x) \
140 x = c1;
141
142 #define CARRY_FORWARD \
143 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
144
145 #define COMBA_FINI
146
147 #define SQRADD(i, j)                                     \
148 asm(                                                     \
149         "movq  %6,%%rax     \n\t"                            \
150         "mulq  %%rax        \n\t"                            \
151         "addq  %%rax,%0     \n\t"                            \
152         "adcq  %%rdx,%1     \n\t"                            \
153         "adcq  $0,%2        \n\t"                            \
154         :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","cc");
155
156 #define SQRADD2(i, j)                                    \
157 asm(                                                     \
158         "movq  %6,%%rax     \n\t"                            \
159         "mulq  %7           \n\t"                            \
160         "addq  %%rax,%0     \n\t"                            \
161         "adcq  %%rdx,%1     \n\t"                            \
162         "adcq  $0,%2        \n\t"                            \
163         "addq  %%rax,%0     \n\t"                            \
164         "adcq  %%rdx,%1     \n\t"                            \
165         "adcq  $0,%2        \n\t"                            \
166         :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j)  :"%rax","%rdx","cc");
167
168 #define SQRADDSC(i, j)                                   \
169 asm(                                                     \
170         "movq  %6,%%rax     \n\t"                            \
171         "mulq  %7           \n\t"                            \
172         "movq  %%rax,%0     \n\t"                            \
173         "movq  %%rdx,%1     \n\t"                            \
174         "xorq  %2,%2        \n\t"                            \
175         :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc");
176
177 #define SQRADDAC(i, j)                                   \
178 asm(                                                     \
179         "movq  %6,%%rax     \n\t"                            \
180         "mulq  %7           \n\t"                            \
181         "addq  %%rax,%0     \n\t"                            \
182         "adcq  %%rdx,%1     \n\t"                            \
183         "adcq  $0,%2        \n\t"                            \
184         :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc");
185
186 #define SQRADDDB                                         \
187 asm(                                                     \
188         "addq %6,%0         \n\t"                            \
189         "adcq %7,%1         \n\t"                            \
190         "adcq %8,%2         \n\t"                            \
191         "addq %6,%0         \n\t"                            \
192         "adcq %7,%1         \n\t"                            \
193         "adcq %8,%2         \n\t"                            \
194         :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
195
196 /******************************************************************************/
197 #elif defined(PSTM_ARM)
198 /* ARM code */
199 //#pragma message ("Using 32 bit ARM Assembly Optimizations")
200
201 #define COMBA_START
202
203 #define CLEAR_CARRY \
204 c0 = c1 = c2 = 0;
205
206 #define COMBA_STORE(x) \
207 x = c0;
208
209 #define COMBA_STORE2(x) \
210 x = c1;
211
212 #define CARRY_FORWARD \
213 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
214
215 #define COMBA_FINI
216
217 /* multiplies point i and j, updates carry "c1" and digit c2 */
218 #define SQRADD(i, j)                                             \
219 asm(                                                             \
220 "  UMULL  r0,r1,%6,%6              \n\t"                         \
221 "  ADDS   %0,%0,r0                 \n\t"                         \
222 "  ADCS   %1,%1,r1                 \n\t"                         \
223 "  ADC    %2,%2,#0                 \n\t"                         \
224 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "%cc");
225
226 /* for squaring some of the terms are doubled... */
227 #define SQRADD2(i, j)                                            \
228 asm(                                                             \
229 "  UMULL  r0,r1,%6,%7              \n\t"                         \
230 "  ADDS   %0,%0,r0                 \n\t"                         \
231 "  ADCS   %1,%1,r1                 \n\t"                         \
232 "  ADC    %2,%2,#0                 \n\t"                         \
233 "  ADDS   %0,%0,r0                 \n\t"                         \
234 "  ADCS   %1,%1,r1                 \n\t"                         \
235 "  ADC    %2,%2,#0                 \n\t"                         \
236 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc");
237
238 #define SQRADDSC(i, j)                                           \
239 asm(                                                             \
240 "  UMULL  %0,%1,%6,%7              \n\t"                         \
241 "  SUB    %2,%2,%2                 \n\t"                         \
242 :"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "%cc");
243
244 #define SQRADDAC(i, j)                                           \
245 asm(                                                             \
246 "  UMULL  r0,r1,%6,%7              \n\t"                         \
247 "  ADDS   %0,%0,r0                 \n\t"                         \
248 "  ADCS   %1,%1,r1                 \n\t"                         \
249 "  ADC    %2,%2,#0                 \n\t"                         \
250 :"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "%cc");
251
252 #define SQRADDDB                                                 \
253 asm(                                                             \
254 "  ADDS  %0,%0,%3                     \n\t"                      \
255 "  ADCS  %1,%1,%4                     \n\t"                      \
256 "  ADC   %2,%2,%5                     \n\t"                      \
257 "  ADDS  %0,%0,%3                     \n\t"                      \
258 "  ADCS  %1,%1,%4                     \n\t"                      \
259 "  ADC   %2,%2,%5                     \n\t"                      \
260 :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "%cc");
261
262 /******************************************************************************/
263 #elif defined(PSTM_MIPS)
264 /* MIPS32 */
265 //#pragma message ("Using 32 bit MIPS Assembly Optimizations")
266
267 #define COMBA_START
268
269 #define CLEAR_CARRY \
270 c0 = c1 = c2 = 0;
271
272 #define COMBA_STORE(x) \
273 x = c0;
274
275 #define COMBA_STORE2(x) \
276 x = c1;
277
278 #define CARRY_FORWARD \
279 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
280
281 #define COMBA_FINI
282
283 /* multiplies point i and j, updates carry "c1" and digit c2 */
284 #define SQRADD(i, j)               \
285 asm(                               \
286         " multu  %6,%6          \n\t"  \
287         " mflo   $12            \n\t"  \
288         " mfhi   $13            \n\t"  \
289         " addu    %0,%0,$12     \n\t"  \
290         " sltu   $12,%0,$12     \n\t"  \
291         " addu    %1,%1,$13     \n\t"  \
292         " sltu   $13,%1,$13     \n\t"  \
293         " addu    %1,%1,$12     \n\t"  \
294         " sltu   $12,%1,$12     \n\t"  \
295         " addu    %2,%2,$13     \n\t"  \
296         " addu    %2,%2,$12     \n\t"  \
297         :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13");
298
299 /* for squaring some of the terms are doubled... */
300 #define SQRADD2(i, j)             \
301 asm(                              \
302         " multu  %6,%7          \n\t" \
303         " mflo   $12            \n\t" \
304         " mfhi   $13            \n\t" \
305         \
306         " addu    %0,%0,$12     \n\t" \
307         " sltu   $14,%0,$12     \n\t" \
308         " addu    %1,%1,$13     \n\t" \
309         " sltu   $15,%1,$13     \n\t" \
310         " addu    %1,%1,$14     \n\t" \
311         " sltu   $14,%1,$14     \n\t" \
312         " addu    %2,%2,$15     \n\t" \
313         " addu    %2,%2,$14     \n\t" \
314         \
315         " addu    %0,%0,$12     \n\t" \
316         " sltu   $14,%0,$12     \n\t" \
317         " addu    %1,%1,$13     \n\t" \
318         " sltu   $15,%1,$13     \n\t" \
319         " addu    %1,%1,$14     \n\t" \
320         " sltu   $14,%1,$14     \n\t" \
321         " addu    %2,%2,$15     \n\t" \
322         " addu    %2,%2,$14     \n\t" \
323         :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15");
324
325 #define SQRADDSC(i, j)             \
326 asm(                               \
327         " multu  %6,%7          \n\t"  \
328         " mflo   %0             \n\t"  \
329         " mfhi   %1             \n\t"  \
330         " xor    %2,%2,%2       \n\t"  \
331         :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "%cc");
332
333 #define SQRADDAC(i, j)            \
334 asm(                              \
335         " multu  %6,%7          \n\t" \
336         " mflo   $12            \n\t" \
337         " mfhi   $13            \n\t" \
338         " addu    %0,%0,$12     \n\t" \
339         " sltu   $12,%0,$12     \n\t" \
340         " addu    %1,%1,$13     \n\t" \
341         " sltu   $13,%1,$13     \n\t" \
342         " addu    %1,%1,$12     \n\t" \
343         " sltu   $12,%1,$12     \n\t" \
344         " addu    %2,%2,$13     \n\t" \
345         " addu    %2,%2,$12     \n\t" \
346         :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14");
347
348 #define SQRADDDB                   \
349 asm(                               \
350         " addu    %0,%0,%3       \n\t" \
351         " sltu   $10,%0,%3       \n\t" \
352         " addu    %1,%1,$10      \n\t" \
353         " sltu   $10,%1,$10      \n\t" \
354         " addu    %1,%1,%4       \n\t" \
355         " sltu   $11,%1,%4       \n\t" \
356         " addu    %2,%2,$10      \n\t" \
357         " addu    %2,%2,$11      \n\t" \
358         " addu    %2,%2,%5       \n\t" \
359         \
360         " addu    %0,%0,%3       \n\t" \
361         " sltu   $10,%0,%3       \n\t" \
362         " addu    %1,%1,$10      \n\t" \
363         " sltu   $10,%1,$10      \n\t" \
364         " addu    %1,%1,%4       \n\t" \
365         " sltu   $11,%1,%4       \n\t" \
366         " addu    %2,%2,$10      \n\t" \
367         " addu    %2,%2,$11      \n\t" \
368         " addu    %2,%2,%5       \n\t" \
369         :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11");
370
371 #else
372 /******************************************************************************/
373 #define PSTM_ISO
374 /* ISO C portable code */
375
376 #define COMBA_START
377
378 #define CLEAR_CARRY \
379    c0 = c1 = c2 = 0;
380
381 #define COMBA_STORE(x) \
382    x = c0;
383
384 #define COMBA_STORE2(x) \
385    x = c1;
386
387 #define CARRY_FORWARD \
388    do { c0 = c1; c1 = c2; c2 = 0; } while (0);
389
390 #define COMBA_FINI
391
392 /* multiplies point i and j, updates carry "c1" and digit c2 */
393 #define SQRADD(i, j)                                                                                                    \
394    do { pstm_word t;                                                                                                    \
395    t = c0 + ((pstm_word)i) * ((pstm_word)j);  c0 = (pstm_digit)t;               \
396    t = c1 + (t >> DIGIT_BIT);                                                                                   \
397    c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT);                              \
398    } while (0);
399
400
401 /* for squaring some of the terms are doubled... */
402 #define SQRADD2(i, j)                                                                                   \
403    do { pstm_word t;                                                                                    \
404    t  = ((pstm_word)i) * ((pstm_word)j);                                                \
405    tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt;                                 \
406    tt = (pstm_word)c1 + (tt >> DIGIT_BIT);                                              \
407    c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT);    \
408    tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt;                                 \
409    tt = (pstm_word)c1 + (tt >> DIGIT_BIT);                                              \
410    c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT);    \
411    } while (0);
412
413 #define SQRADDSC(i, j)                                                                          \
414    do { pstm_word t;                                                                            \
415           t =  ((pstm_word)i) * ((pstm_word)j);                                 \
416           sc0 = (pstm_digit)t; sc1 = (pstm_digit)(t >> DIGIT_BIT); sc2 = 0;     \
417    } while (0);
418
419 #define SQRADDAC(i, j)                                                                                                          \
420    do { pstm_word t;                                                                                                            \
421    t = ((pstm_word)sc0) + ((pstm_word)i) * ((pstm_word)j);                                      \
422    sc0 = (pstm_digit)t;                                                                                                         \
423    t = ((pstm_word)sc1) + (t >> DIGIT_BIT); sc1 = (pstm_digit)t;                        \
424    sc2 += (pstm_digit)(t >> DIGIT_BIT);                                                                         \
425    } while (0);
426
427 #define SQRADDDB                                                                                                                        \
428    do { pstm_word t;                                                                                                            \
429    t = ((pstm_word)sc0) + ((pstm_word)sc0) + ((pstm_word)c0);                           \
430    c0 = (pstm_digit)t;                                                                                                          \
431    t = ((pstm_word)sc1) + ((pstm_word)sc1) + c1 + (t >> DIGIT_BIT);                     \
432    c1 = (pstm_digit)t;                                                                                                          \
433    c2 = c2 + sc2 + sc2 + (pstm_digit)(t >> DIGIT_BIT);                                          \
434    } while (0);
435
436 #endif /* ISO_C */
437
438 /******************************************************************************/
439 /*
440         Non-unrolled comba squarer
441  */
442 //bbox: pool unused
443 #define pstm_sqr_comba_gen(pool, A, B, paD, paDlen) \
444         pstm_sqr_comba_gen(      A, B, paD, paDlen)
445 static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
446                         pstm_digit *paD, uint32 paDlen)
447 {
448         int16           paDfail, pa;
449         int32       ix, iz;
450         pstm_digit  c0, c1, c2, *dst;
451 #ifdef PSTM_ISO
452         pstm_word   tt;
453 #endif
454
455         paDfail = 0;
456         /* get size of output and trim */
457         pa = A->used + A->used;
458
459         /* number of output digits to produce */
460         COMBA_START;
461         CLEAR_CARRY;
462 /*
463         If b is not large enough grow it and continue
464 */
465         if (B->alloc < pa) {
466                 if (pstm_grow(B, pa) != PSTM_OKAY) {
467                         return PS_MEM_FAIL;
468                 }
469         }
470         if (paD != NULL) {
471                 if (paDlen < (sizeof(pstm_digit) * pa)) {
472                         paDfail = 1; /* have a paD, but it's not big enough */
473                         dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
474                 } else {
475                         dst = paD;
476                         memset(dst, 0x0, paDlen);
477                 }
478         } else {
479                 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
480         }
481
482         for (ix = 0; ix < pa; ix++) {
483                 int32      tx, ty, iy;
484                 pstm_digit *tmpy, *tmpx;
485
486                 /* get offsets into the two bignums */
487                 ty = min(A->used-1, ix);
488                 tx = ix - ty;
489
490                 /* setup temp aliases */
491                 tmpx = A->dp + tx;
492                 tmpy = A->dp + ty;
493
494 /*
495                         This is the number of times the loop will iterate,
496                                 while (tx++ < a->used && ty-- >= 0) { ... }
497 */
498                 iy = min(A->used-tx, ty+1);
499
500 /*
501                 now for squaring tx can never equal ty. We halve the distance since
502                 they approach at a rate of 2x and we have to round because odd cases
503                 need to be executed
504 */
505                 iy = min(iy, (ty-tx+1)>>1);
506
507                 /* forward carries */
508                 CARRY_FORWARD;
509
510                 /* execute loop */
511                 for (iz = 0; iz < iy; iz++) {
512                         SQRADD2(*tmpx++, *tmpy--);
513                 }
514
515                 /* even columns have the square term in them */
516                 if ((ix&1) == 0) {
517                         SQRADD(A->dp[ix>>1], A->dp[ix>>1]);
518                 }
519
520                 /* store it */
521                 COMBA_STORE(dst[ix]);
522         }
523
524         COMBA_FINI;
525 /*
526         setup dest
527  */
528         iz  = B->used;
529         B->used = pa;
530         {
531                 pstm_digit *tmpc;
532                 tmpc = B->dp;
533                 for (ix = 0; ix < pa; ix++) {
534                         *tmpc++ = dst[ix];
535                 }
536                 /*      clear unused digits (that existed in the old copy of c) */
537                 for (; ix < iz; ix++) {
538                         *tmpc++ = 0;
539                 }
540         }
541         pstm_clamp(B);
542
543         if ((paD == NULL) || paDfail == 1) {
544                 psFree(dst, pool);
545         }
546         return PS_SUCCESS;
547 }
548
549 /******************************************************************************/
550 /*
551         Unrolled Comba loop for 1024 bit keys
552  */
553 #ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
554 static int32 pstm_sqr_comba16(pstm_int *A, pstm_int *B)
555 {
556         pstm_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2;
557 #ifdef PSTM_ISO
558         pstm_word   tt;
559 #endif
560
561         if (B->alloc < 32) {
562                 if (pstm_grow(B, 32) != PSTM_OKAY) {
563                         return PS_MEM_FAIL;
564                 }
565         }
566         a = A->dp;
567         sc0 = sc1 = sc2 = 0;
568
569         COMBA_START;
570
571    /* clear carries */
572    CLEAR_CARRY;
573
574    /* output 0 */
575    SQRADD(a[0],a[0]);
576    COMBA_STORE(b[0]);
577
578    /* output 1 */
579    CARRY_FORWARD;
580    SQRADD2(a[0], a[1]);
581    COMBA_STORE(b[1]);
582
583    /* output 2 */
584    CARRY_FORWARD;
585    SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
586    COMBA_STORE(b[2]);
587
588    /* output 3 */
589    CARRY_FORWARD;
590    SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
591    COMBA_STORE(b[3]);
592
593    /* output 4 */
594    CARRY_FORWARD;
595    SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
596    COMBA_STORE(b[4]);
597
598    /* output 5 */
599    CARRY_FORWARD;
600    SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
601    COMBA_STORE(b[5]);
602
603    /* output 6 */
604    CARRY_FORWARD;
605    SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
606    COMBA_STORE(b[6]);
607
608    /* output 7 */
609    CARRY_FORWARD;
610    SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
611    COMBA_STORE(b[7]);
612
613    /* output 8 */
614    CARRY_FORWARD;
615    SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
616    COMBA_STORE(b[8]);
617
618    /* output 9 */
619    CARRY_FORWARD;
620    SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
621    COMBA_STORE(b[9]);
622
623    /* output 10 */
624    CARRY_FORWARD;
625    SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
626    COMBA_STORE(b[10]);
627
628    /* output 11 */
629    CARRY_FORWARD;
630    SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
631    COMBA_STORE(b[11]);
632
633    /* output 12 */
634    CARRY_FORWARD;
635    SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
636    COMBA_STORE(b[12]);
637
638    /* output 13 */
639    CARRY_FORWARD;
640    SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
641    COMBA_STORE(b[13]);
642
643    /* output 14 */
644    CARRY_FORWARD;
645    SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
646    COMBA_STORE(b[14]);
647
648    /* output 15 */
649    CARRY_FORWARD;
650    SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
651    COMBA_STORE(b[15]);
652
653    /* output 16 */
654    CARRY_FORWARD;
655    SQRADDSC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
656    COMBA_STORE(b[16]);
657
658    /* output 17 */
659    CARRY_FORWARD;
660    SQRADDSC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
661    COMBA_STORE(b[17]);
662
663    /* output 18 */
664    CARRY_FORWARD;
665    SQRADDSC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
666    COMBA_STORE(b[18]);
667
668    /* output 19 */
669    CARRY_FORWARD;
670    SQRADDSC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
671    COMBA_STORE(b[19]);
672
673    /* output 20 */
674    CARRY_FORWARD;
675    SQRADDSC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
676    COMBA_STORE(b[20]);
677
678    /* output 21 */
679    CARRY_FORWARD;
680    SQRADDSC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
681    COMBA_STORE(b[21]);
682
683    /* output 22 */
684    CARRY_FORWARD;
685    SQRADDSC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
686    COMBA_STORE(b[22]);
687
688    /* output 23 */
689    CARRY_FORWARD;
690    SQRADDSC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
691    COMBA_STORE(b[23]);
692
693    /* output 24 */
694    CARRY_FORWARD;
695    SQRADDSC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
696    COMBA_STORE(b[24]);
697
698    /* output 25 */
699    CARRY_FORWARD;
700    SQRADDSC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
701    COMBA_STORE(b[25]);
702
703    /* output 26 */
704    CARRY_FORWARD;
705    SQRADD2(a[11], a[15]); SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]);
706    COMBA_STORE(b[26]);
707
708    /* output 27 */
709    CARRY_FORWARD;
710    SQRADD2(a[12], a[15]); SQRADD2(a[13], a[14]);
711    COMBA_STORE(b[27]);
712
713    /* output 28 */
714    CARRY_FORWARD;
715    SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]);
716    COMBA_STORE(b[28]);
717
718    /* output 29 */
719    CARRY_FORWARD;
720    SQRADD2(a[14], a[15]);
721    COMBA_STORE(b[29]);
722
723    /* output 30 */
724    CARRY_FORWARD;
725    SQRADD(a[15], a[15]);
726    COMBA_STORE(b[30]);
727    COMBA_STORE2(b[31]);
728    COMBA_FINI;
729
730    B->used = 32;
731    B->sign = PSTM_ZPOS;
732    memcpy(B->dp, b, 32 * sizeof(pstm_digit));
733    pstm_clamp(B);
734    return PSTM_OKAY;
735 }
736 #endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */
737
738
739 #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
740 static int32 pstm_sqr_comba32(pstm_int *A, pstm_int *B)
741 {
742    pstm_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2;
743 #ifdef PSTM_ISO
744    pstm_word tt;
745 #endif
746
747         if (B->alloc < 64) {
748                 if (pstm_grow(B, 64) != PSTM_OKAY) {
749                         return PS_MEM_FAIL;
750                 }
751         }
752         sc0 = sc1 = sc2 = 0;
753    a = A->dp;
754    COMBA_START;
755
756    /* clear carries */
757    CLEAR_CARRY;
758
759    /* output 0 */
760    SQRADD(a[0],a[0]);
761    COMBA_STORE(b[0]);
762
763    /* output 1 */
764    CARRY_FORWARD;
765    SQRADD2(a[0], a[1]);
766    COMBA_STORE(b[1]);
767
768    /* output 2 */
769    CARRY_FORWARD;
770    SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
771    COMBA_STORE(b[2]);
772
773    /* output 3 */
774    CARRY_FORWARD;
775    SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
776    COMBA_STORE(b[3]);
777
778    /* output 4 */
779    CARRY_FORWARD;
780    SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
781    COMBA_STORE(b[4]);
782
783    /* output 5 */
784    CARRY_FORWARD;
785    SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
786    COMBA_STORE(b[5]);
787
788    /* output 6 */
789    CARRY_FORWARD;
790    SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
791    COMBA_STORE(b[6]);
792
793    /* output 7 */
794    CARRY_FORWARD;
795    SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
796    COMBA_STORE(b[7]);
797
798    /* output 8 */
799    CARRY_FORWARD;
800    SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
801    COMBA_STORE(b[8]);
802
803    /* output 9 */
804    CARRY_FORWARD;
805    SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
806    COMBA_STORE(b[9]);
807
808    /* output 10 */
809    CARRY_FORWARD;
810    SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
811    COMBA_STORE(b[10]);
812
813    /* output 11 */
814    CARRY_FORWARD;
815    SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
816    COMBA_STORE(b[11]);
817
818    /* output 12 */
819    CARRY_FORWARD;
820    SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
821    COMBA_STORE(b[12]);
822
823    /* output 13 */
824    CARRY_FORWARD;
825    SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
826    COMBA_STORE(b[13]);
827
828    /* output 14 */
829    CARRY_FORWARD;
830    SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
831    COMBA_STORE(b[14]);
832
833    /* output 15 */
834    CARRY_FORWARD;
835    SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
836    COMBA_STORE(b[15]);
837
838    /* output 16 */
839    CARRY_FORWARD;
840    SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
841    COMBA_STORE(b[16]);
842
843    /* output 17 */
844    CARRY_FORWARD;
845    SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
846    COMBA_STORE(b[17]);
847
848    /* output 18 */
849    CARRY_FORWARD;
850    SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
851    COMBA_STORE(b[18]);
852
853    /* output 19 */
854    CARRY_FORWARD;
855    SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
856    COMBA_STORE(b[19]);
857
858    /* output 20 */
859    CARRY_FORWARD;
860    SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
861    COMBA_STORE(b[20]);
862
863    /* output 21 */
864    CARRY_FORWARD;
865    SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
866    COMBA_STORE(b[21]);
867
868    /* output 22 */
869    CARRY_FORWARD;
870    SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
871    COMBA_STORE(b[22]);
872
873    /* output 23 */
874    CARRY_FORWARD;
875    SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
876    COMBA_STORE(b[23]);
877
878    /* output 24 */
879    CARRY_FORWARD;
880    SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
881    COMBA_STORE(b[24]);
882
883    /* output 25 */
884    CARRY_FORWARD;
885    SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
886    COMBA_STORE(b[25]);
887
888    /* output 26 */
889    CARRY_FORWARD;
890    SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
891    COMBA_STORE(b[26]);
892
893    /* output 27 */
894    CARRY_FORWARD;
895    SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
896    COMBA_STORE(b[27]);
897
898    /* output 28 */
899    CARRY_FORWARD;
900    SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
901    COMBA_STORE(b[28]);
902
903    /* output 29 */
904    CARRY_FORWARD;
905    SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
906    COMBA_STORE(b[29]);
907
908    /* output 30 */
909    CARRY_FORWARD;
910    SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
911    COMBA_STORE(b[30]);
912
913    /* output 31 */
914    CARRY_FORWARD;
915    SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
916    COMBA_STORE(b[31]);
917
918    /* output 32 */
919    CARRY_FORWARD;
920    SQRADDSC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
921    COMBA_STORE(b[32]);
922
923    /* output 33 */
924    CARRY_FORWARD;
925    SQRADDSC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
926    COMBA_STORE(b[33]);
927
928    /* output 34 */
929    CARRY_FORWARD;
930    SQRADDSC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
931    COMBA_STORE(b[34]);
932
933    /* output 35 */
934    CARRY_FORWARD;
935    SQRADDSC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
936    COMBA_STORE(b[35]);
937
938    /* output 36 */
939    CARRY_FORWARD;
940    SQRADDSC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
941    COMBA_STORE(b[36]);
942
943    /* output 37 */
944    CARRY_FORWARD;
945    SQRADDSC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
946    COMBA_STORE(b[37]);
947
948    /* output 38 */
949    CARRY_FORWARD;
950    SQRADDSC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
951    COMBA_STORE(b[38]);
952
953    /* output 39 */
954    CARRY_FORWARD;
955    SQRADDSC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
956    COMBA_STORE(b[39]);
957
958    /* output 40 */
959    CARRY_FORWARD;
960    SQRADDSC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
961    COMBA_STORE(b[40]);
962
963    /* output 41 */
964    CARRY_FORWARD;
965    SQRADDSC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
966    COMBA_STORE(b[41]);
967
968    /* output 42 */
969    CARRY_FORWARD;
970    SQRADDSC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]);
971    COMBA_STORE(b[42]);
972
973    /* output 43 */
974    CARRY_FORWARD;
975    SQRADDSC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB;
976    COMBA_STORE(b[43]);
977
978    /* output 44 */
979    CARRY_FORWARD;
980    SQRADDSC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]);
981    COMBA_STORE(b[44]);
982
983    /* output 45 */
984    CARRY_FORWARD;
985    SQRADDSC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB;
986    COMBA_STORE(b[45]);
987
988    /* output 46 */
989    CARRY_FORWARD;
990    SQRADDSC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]);
991    COMBA_STORE(b[46]);
992
993    /* output 47 */
994    CARRY_FORWARD;
995    SQRADDSC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB;
996    COMBA_STORE(b[47]);
997
998    /* output 48 */
999    CARRY_FORWARD;
1000    SQRADDSC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]);
1001    COMBA_STORE(b[48]);
1002
1003    /* output 49 */
1004    CARRY_FORWARD;
1005    SQRADDSC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB;
1006    COMBA_STORE(b[49]);
1007
1008    /* output 50 */
1009    CARRY_FORWARD;
1010    SQRADDSC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]);
1011    COMBA_STORE(b[50]);
1012
1013    /* output 51 */
1014    CARRY_FORWARD;
1015    SQRADDSC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB;
1016    COMBA_STORE(b[51]);
1017
1018    /* output 52 */
1019    CARRY_FORWARD;
1020    SQRADDSC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]);
1021    COMBA_STORE(b[52]);
1022
1023    /* output 53 */
1024    CARRY_FORWARD;
1025    SQRADDSC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB;
1026    COMBA_STORE(b[53]);
1027
1028    /* output 54 */
1029    CARRY_FORWARD;
1030    SQRADDSC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]);
1031    COMBA_STORE(b[54]);
1032
1033    /* output 55 */
1034    CARRY_FORWARD;
1035    SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB;
1036    COMBA_STORE(b[55]);
1037
1038    /* output 56 */
1039    CARRY_FORWARD;
1040    SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]);
1041    COMBA_STORE(b[56]);
1042
1043    /* output 57 */
1044    CARRY_FORWARD;
1045    SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB;
1046    COMBA_STORE(b[57]);
1047
1048    /* output 58 */
1049    CARRY_FORWARD;
1050    SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]);
1051    COMBA_STORE(b[58]);
1052
1053    /* output 59 */
1054    CARRY_FORWARD;
1055    SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]);
1056    COMBA_STORE(b[59]);
1057
1058    /* output 60 */
1059    CARRY_FORWARD;
1060    SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]);
1061    COMBA_STORE(b[60]);
1062
1063    /* output 61 */
1064    CARRY_FORWARD;
1065    SQRADD2(a[30], a[31]);
1066    COMBA_STORE(b[61]);
1067
1068    /* output 62 */
1069    CARRY_FORWARD;
1070    SQRADD(a[31], a[31]);
1071    COMBA_STORE(b[62]);
1072    COMBA_STORE2(b[63]);
1073    COMBA_FINI;
1074
1075    B->used = 64;
1076    B->sign = PSTM_ZPOS;
1077    memcpy(B->dp, b, 64 * sizeof(pstm_digit));
1078    pstm_clamp(B);
1079    return PSTM_OKAY;
1080 }
1081 #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1082
1083 /******************************************************************************/
1084 /*
1085  */
1086 int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_digit *paD,
1087                 uint32 paDlen)
1088 {
1089 #ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
1090         if (A->used == 16) {
1091                 return pstm_sqr_comba16(A, B);
1092         } else {
1093 #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
1094                 if (A->used == 32) {
1095                         return pstm_sqr_comba32(A, B);
1096                 }
1097 #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1098                 return pstm_sqr_comba_gen(pool, A, B, paD, paDlen);
1099         }
1100 #else
1101 #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
1102         if (A->used == 32) {
1103                 return pstm_sqr_comba32(A, B);
1104         }
1105 #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1106         return pstm_sqr_comba_gen(pool, A, B, paD, paDlen);
1107 #endif
1108 }
1109
1110 #endif /* DISABLE_PSTM */
1111 /******************************************************************************/