Clean-up *_DEBUG options.
[openssl.git] / crypto / bn / bn_asm.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57
58 #include <assert.h>
59 #include <openssl/crypto.h>
60 #include "internal/cryptlib.h"
61 #include "bn_lcl.h"
62
63 #if defined(BN_LLONG) || defined(BN_UMULT_HIGH)
64
65 BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
66                           BN_ULONG w)
67 {
68     BN_ULONG c1 = 0;
69
70     assert(num >= 0);
71     if (num <= 0)
72         return (c1);
73
74 # ifndef OPENSSL_SMALL_FOOTPRINT
75     while (num & ~3) {
76         mul_add(rp[0], ap[0], w, c1);
77         mul_add(rp[1], ap[1], w, c1);
78         mul_add(rp[2], ap[2], w, c1);
79         mul_add(rp[3], ap[3], w, c1);
80         ap += 4;
81         rp += 4;
82         num -= 4;
83     }
84 # endif
85     while (num) {
86         mul_add(rp[0], ap[0], w, c1);
87         ap++;
88         rp++;
89         num--;
90     }
91
92     return (c1);
93 }
94
95 BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
96 {
97     BN_ULONG c1 = 0;
98
99     assert(num >= 0);
100     if (num <= 0)
101         return (c1);
102
103 # ifndef OPENSSL_SMALL_FOOTPRINT
104     while (num & ~3) {
105         mul(rp[0], ap[0], w, c1);
106         mul(rp[1], ap[1], w, c1);
107         mul(rp[2], ap[2], w, c1);
108         mul(rp[3], ap[3], w, c1);
109         ap += 4;
110         rp += 4;
111         num -= 4;
112     }
113 # endif
114     while (num) {
115         mul(rp[0], ap[0], w, c1);
116         ap++;
117         rp++;
118         num--;
119     }
120     return (c1);
121 }
122
123 void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
124 {
125     assert(n >= 0);
126     if (n <= 0)
127         return;
128
129 # ifndef OPENSSL_SMALL_FOOTPRINT
130     while (n & ~3) {
131         sqr(r[0], r[1], a[0]);
132         sqr(r[2], r[3], a[1]);
133         sqr(r[4], r[5], a[2]);
134         sqr(r[6], r[7], a[3]);
135         a += 4;
136         r += 8;
137         n -= 4;
138     }
139 # endif
140     while (n) {
141         sqr(r[0], r[1], a[0]);
142         a++;
143         r += 2;
144         n--;
145     }
146 }
147
148 #else                           /* !(defined(BN_LLONG) ||
149                                  * defined(BN_UMULT_HIGH)) */
150
151 BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
152                           BN_ULONG w)
153 {
154     BN_ULONG c = 0;
155     BN_ULONG bl, bh;
156
157     assert(num >= 0);
158     if (num <= 0)
159         return ((BN_ULONG)0);
160
161     bl = LBITS(w);
162     bh = HBITS(w);
163
164 # ifndef OPENSSL_SMALL_FOOTPRINT
165     while (num & ~3) {
166         mul_add(rp[0], ap[0], bl, bh, c);
167         mul_add(rp[1], ap[1], bl, bh, c);
168         mul_add(rp[2], ap[2], bl, bh, c);
169         mul_add(rp[3], ap[3], bl, bh, c);
170         ap += 4;
171         rp += 4;
172         num -= 4;
173     }
174 # endif
175     while (num) {
176         mul_add(rp[0], ap[0], bl, bh, c);
177         ap++;
178         rp++;
179         num--;
180     }
181     return (c);
182 }
183
184 BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
185 {
186     BN_ULONG carry = 0;
187     BN_ULONG bl, bh;
188
189     assert(num >= 0);
190     if (num <= 0)
191         return ((BN_ULONG)0);
192
193     bl = LBITS(w);
194     bh = HBITS(w);
195
196 # ifndef OPENSSL_SMALL_FOOTPRINT
197     while (num & ~3) {
198         mul(rp[0], ap[0], bl, bh, carry);
199         mul(rp[1], ap[1], bl, bh, carry);
200         mul(rp[2], ap[2], bl, bh, carry);
201         mul(rp[3], ap[3], bl, bh, carry);
202         ap += 4;
203         rp += 4;
204         num -= 4;
205     }
206 # endif
207     while (num) {
208         mul(rp[0], ap[0], bl, bh, carry);
209         ap++;
210         rp++;
211         num--;
212     }
213     return (carry);
214 }
215
216 void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
217 {
218     assert(n >= 0);
219     if (n <= 0)
220         return;
221
222 # ifndef OPENSSL_SMALL_FOOTPRINT
223     while (n & ~3) {
224         sqr64(r[0], r[1], a[0]);
225         sqr64(r[2], r[3], a[1]);
226         sqr64(r[4], r[5], a[2]);
227         sqr64(r[6], r[7], a[3]);
228         a += 4;
229         r += 8;
230         n -= 4;
231     }
232 # endif
233     while (n) {
234         sqr64(r[0], r[1], a[0]);
235         a++;
236         r += 2;
237         n--;
238     }
239 }
240
241 #endif                          /* !(defined(BN_LLONG) ||
242                                  * defined(BN_UMULT_HIGH)) */
243
244 #if defined(BN_LLONG) && defined(BN_DIV2W)
245
246 BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
247 {
248     return ((BN_ULONG)(((((BN_ULLONG) h) << BN_BITS2) | l) / (BN_ULLONG) d));
249 }
250
251 #else
252
253 /* Divide h,l by d and return the result. */
254 /* I need to test this some more :-( */
255 BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
256 {
257     BN_ULONG dh, dl, q, ret = 0, th, tl, t;
258     int i, count = 2;
259
260     if (d == 0)
261         return (BN_MASK2);
262
263     i = BN_num_bits_word(d);
264     assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
265
266     i = BN_BITS2 - i;
267     if (h >= d)
268         h -= d;
269
270     if (i) {
271         d <<= i;
272         h = (h << i) | (l >> (BN_BITS2 - i));
273         l <<= i;
274     }
275     dh = (d & BN_MASK2h) >> BN_BITS4;
276     dl = (d & BN_MASK2l);
277     for (;;) {
278         if ((h >> BN_BITS4) == dh)
279             q = BN_MASK2l;
280         else
281             q = h / dh;
282
283         th = q * dh;
284         tl = dl * q;
285         for (;;) {
286             t = h - th;
287             if ((t & BN_MASK2h) ||
288                 ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4))))
289                 break;
290             q--;
291             th -= dh;
292             tl -= dl;
293         }
294         t = (tl >> BN_BITS4);
295         tl = (tl << BN_BITS4) & BN_MASK2h;
296         th += t;
297
298         if (l < tl)
299             th++;
300         l -= tl;
301         if (h < th) {
302             h += d;
303             q--;
304         }
305         h -= th;
306
307         if (--count == 0)
308             break;
309
310         ret = q << BN_BITS4;
311         h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
312         l = (l & BN_MASK2l) << BN_BITS4;
313     }
314     ret |= q;
315     return (ret);
316 }
317 #endif                          /* !defined(BN_LLONG) && defined(BN_DIV2W) */
318
319 #ifdef BN_LLONG
320 BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
321                       int n)
322 {
323     BN_ULLONG ll = 0;
324
325     assert(n >= 0);
326     if (n <= 0)
327         return ((BN_ULONG)0);
328
329 # ifndef OPENSSL_SMALL_FOOTPRINT
330     while (n & ~3) {
331         ll += (BN_ULLONG) a[0] + b[0];
332         r[0] = (BN_ULONG)ll & BN_MASK2;
333         ll >>= BN_BITS2;
334         ll += (BN_ULLONG) a[1] + b[1];
335         r[1] = (BN_ULONG)ll & BN_MASK2;
336         ll >>= BN_BITS2;
337         ll += (BN_ULLONG) a[2] + b[2];
338         r[2] = (BN_ULONG)ll & BN_MASK2;
339         ll >>= BN_BITS2;
340         ll += (BN_ULLONG) a[3] + b[3];
341         r[3] = (BN_ULONG)ll & BN_MASK2;
342         ll >>= BN_BITS2;
343         a += 4;
344         b += 4;
345         r += 4;
346         n -= 4;
347     }
348 # endif
349     while (n) {
350         ll += (BN_ULLONG) a[0] + b[0];
351         r[0] = (BN_ULONG)ll & BN_MASK2;
352         ll >>= BN_BITS2;
353         a++;
354         b++;
355         r++;
356         n--;
357     }
358     return ((BN_ULONG)ll);
359 }
360 #else                           /* !BN_LLONG */
361 BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
362                       int n)
363 {
364     BN_ULONG c, l, t;
365
366     assert(n >= 0);
367     if (n <= 0)
368         return ((BN_ULONG)0);
369
370     c = 0;
371 # ifndef OPENSSL_SMALL_FOOTPRINT
372     while (n & ~3) {
373         t = a[0];
374         t = (t + c) & BN_MASK2;
375         c = (t < c);
376         l = (t + b[0]) & BN_MASK2;
377         c += (l < t);
378         r[0] = l;
379         t = a[1];
380         t = (t + c) & BN_MASK2;
381         c = (t < c);
382         l = (t + b[1]) & BN_MASK2;
383         c += (l < t);
384         r[1] = l;
385         t = a[2];
386         t = (t + c) & BN_MASK2;
387         c = (t < c);
388         l = (t + b[2]) & BN_MASK2;
389         c += (l < t);
390         r[2] = l;
391         t = a[3];
392         t = (t + c) & BN_MASK2;
393         c = (t < c);
394         l = (t + b[3]) & BN_MASK2;
395         c += (l < t);
396         r[3] = l;
397         a += 4;
398         b += 4;
399         r += 4;
400         n -= 4;
401     }
402 # endif
403     while (n) {
404         t = a[0];
405         t = (t + c) & BN_MASK2;
406         c = (t < c);
407         l = (t + b[0]) & BN_MASK2;
408         c += (l < t);
409         r[0] = l;
410         a++;
411         b++;
412         r++;
413         n--;
414     }
415     return ((BN_ULONG)c);
416 }
417 #endif                          /* !BN_LLONG */
418
419 BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
420                       int n)
421 {
422     BN_ULONG t1, t2;
423     int c = 0;
424
425     assert(n >= 0);
426     if (n <= 0)
427         return ((BN_ULONG)0);
428
429 #ifndef OPENSSL_SMALL_FOOTPRINT
430     while (n & ~3) {
431         t1 = a[0];
432         t2 = b[0];
433         r[0] = (t1 - t2 - c) & BN_MASK2;
434         if (t1 != t2)
435             c = (t1 < t2);
436         t1 = a[1];
437         t2 = b[1];
438         r[1] = (t1 - t2 - c) & BN_MASK2;
439         if (t1 != t2)
440             c = (t1 < t2);
441         t1 = a[2];
442         t2 = b[2];
443         r[2] = (t1 - t2 - c) & BN_MASK2;
444         if (t1 != t2)
445             c = (t1 < t2);
446         t1 = a[3];
447         t2 = b[3];
448         r[3] = (t1 - t2 - c) & BN_MASK2;
449         if (t1 != t2)
450             c = (t1 < t2);
451         a += 4;
452         b += 4;
453         r += 4;
454         n -= 4;
455     }
456 #endif
457     while (n) {
458         t1 = a[0];
459         t2 = b[0];
460         r[0] = (t1 - t2 - c) & BN_MASK2;
461         if (t1 != t2)
462             c = (t1 < t2);
463         a++;
464         b++;
465         r++;
466         n--;
467     }
468     return (c);
469 }
470
471 #if defined(BN_MUL_COMBA) && !defined(OPENSSL_SMALL_FOOTPRINT)
472
473 # undef bn_mul_comba8
474 # undef bn_mul_comba4
475 # undef bn_sqr_comba8
476 # undef bn_sqr_comba4
477
478 /* mul_add_c(a,b,c0,c1,c2)  -- c+=a*b for three word number c=(c2,c1,c0) */
479 /* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
480 /* sqr_add_c(a,i,c0,c1,c2)  -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
481 /*
482  * sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number
483  * c=(c2,c1,c0)
484  */
485
486 # ifdef BN_LLONG
487 /*
488  * Keep in mind that additions to multiplication result can not
489  * overflow, because its high half cannot be all-ones.
490  */
491 #  define mul_add_c(a,b,c0,c1,c2)       do {    \
492         BN_ULONG hi;                            \
493         BN_ULLONG t = (BN_ULLONG)(a)*(b);       \
494         t += c0;                /* no carry */  \
495         c0 = (BN_ULONG)Lw(t);                   \
496         hi = (BN_ULONG)Hw(t);                   \
497         c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
498         } while(0)
499
500 #  define mul_add_c2(a,b,c0,c1,c2)      do {    \
501         BN_ULONG hi;                            \
502         BN_ULLONG t = (BN_ULLONG)(a)*(b);       \
503         BN_ULLONG tt = t+c0;    /* no carry */  \
504         c0 = (BN_ULONG)Lw(tt);                  \
505         hi = (BN_ULONG)Hw(tt);                  \
506         c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
507         t += c0;                /* no carry */  \
508         c0 = (BN_ULONG)Lw(t);                   \
509         hi = (BN_ULONG)Hw(t);                   \
510         c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
511         } while(0)
512
513 #  define sqr_add_c(a,i,c0,c1,c2)       do {    \
514         BN_ULONG hi;                            \
515         BN_ULLONG t = (BN_ULLONG)a[i]*a[i];     \
516         t += c0;                /* no carry */  \
517         c0 = (BN_ULONG)Lw(t);                   \
518         hi = (BN_ULONG)Hw(t);                   \
519         c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
520         } while(0)
521
522 #  define sqr_add_c2(a,i,j,c0,c1,c2) \
523         mul_add_c2((a)[i],(a)[j],c0,c1,c2)
524
525 # elif defined(BN_UMULT_LOHI)
526 /*
527  * Keep in mind that additions to hi can not overflow, because
528  * the high word of a multiplication result cannot be all-ones.
529  */
530 #  define mul_add_c(a,b,c0,c1,c2)       do {    \
531         BN_ULONG ta = (a), tb = (b);            \
532         BN_ULONG lo, hi;                        \
533         BN_UMULT_LOHI(lo,hi,ta,tb);             \
534         c0 += lo; hi += (c0<lo)?1:0;            \
535         c1 += hi; c2 += (c1<hi)?1:0;            \
536         } while(0)
537
538 #  define mul_add_c2(a,b,c0,c1,c2)      do {    \
539         BN_ULONG ta = (a), tb = (b);            \
540         BN_ULONG lo, hi, tt;                    \
541         BN_UMULT_LOHI(lo,hi,ta,tb);             \
542         c0 += lo; tt = hi+((c0<lo)?1:0);        \
543         c1 += tt; c2 += (c1<tt)?1:0;            \
544         c0 += lo; hi += (c0<lo)?1:0;            \
545         c1 += hi; c2 += (c1<hi)?1:0;            \
546         } while(0)
547
548 #  define sqr_add_c(a,i,c0,c1,c2)       do {    \
549         BN_ULONG ta = (a)[i];                   \
550         BN_ULONG lo, hi;                        \
551         BN_UMULT_LOHI(lo,hi,ta,ta);             \
552         c0 += lo; hi += (c0<lo)?1:0;            \
553         c1 += hi; c2 += (c1<hi)?1:0;            \
554         } while(0)
555
556 #  define sqr_add_c2(a,i,j,c0,c1,c2)    \
557         mul_add_c2((a)[i],(a)[j],c0,c1,c2)
558
559 # elif defined(BN_UMULT_HIGH)
560 /*
561  * Keep in mind that additions to hi can not overflow, because
562  * the high word of a multiplication result cannot be all-ones.
563  */
564 #  define mul_add_c(a,b,c0,c1,c2)       do {    \
565         BN_ULONG ta = (a), tb = (b);            \
566         BN_ULONG lo = ta * tb;                  \
567         BN_ULONG hi = BN_UMULT_HIGH(ta,tb);     \
568         c0 += lo; hi += (c0<lo)?1:0;            \
569         c1 += hi; c2 += (c1<hi)?1:0;            \
570         } while(0)
571
572 #  define mul_add_c2(a,b,c0,c1,c2)      do {    \
573         BN_ULONG ta = (a), tb = (b), tt;        \
574         BN_ULONG lo = ta * tb;                  \
575         BN_ULONG hi = BN_UMULT_HIGH(ta,tb);     \
576         c0 += lo; tt = hi + ((c0<lo)?1:0);      \
577         c1 += tt; c2 += (c1<tt)?1:0;            \
578         c0 += lo; hi += (c0<lo)?1:0;            \
579         c1 += hi; c2 += (c1<hi)?1:0;            \
580         } while(0)
581
582 #  define sqr_add_c(a,i,c0,c1,c2)       do {    \
583         BN_ULONG ta = (a)[i];                   \
584         BN_ULONG lo = ta * ta;                  \
585         BN_ULONG hi = BN_UMULT_HIGH(ta,ta);     \
586         c0 += lo; hi += (c0<lo)?1:0;            \
587         c1 += hi; c2 += (c1<hi)?1:0;            \
588         } while(0)
589
590 #  define sqr_add_c2(a,i,j,c0,c1,c2)      \
591         mul_add_c2((a)[i],(a)[j],c0,c1,c2)
592
593 # else                          /* !BN_LLONG */
594 /*
595  * Keep in mind that additions to hi can not overflow, because
596  * the high word of a multiplication result cannot be all-ones.
597  */
598 #  define mul_add_c(a,b,c0,c1,c2)       do {    \
599         BN_ULONG lo = LBITS(a), hi = HBITS(a);  \
600         BN_ULONG bl = LBITS(b), bh = HBITS(b);  \
601         mul64(lo,hi,bl,bh);                     \
602         c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
603         c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
604         } while(0)
605
606 #  define mul_add_c2(a,b,c0,c1,c2)      do {    \
607         BN_ULONG tt;                            \
608         BN_ULONG lo = LBITS(a), hi = HBITS(a);  \
609         BN_ULONG bl = LBITS(b), bh = HBITS(b);  \
610         mul64(lo,hi,bl,bh);                     \
611         tt = hi;                                \
612         c0 = (c0+lo)&BN_MASK2; if (c0<lo) tt++; \
613         c1 = (c1+tt)&BN_MASK2; if (c1<tt) c2++; \
614         c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
615         c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
616         } while(0)
617
618 #  define sqr_add_c(a,i,c0,c1,c2)       do {    \
619         BN_ULONG lo, hi;                        \
620         sqr64(lo,hi,(a)[i]);                    \
621         c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
622         c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
623         } while(0)
624
625 #  define sqr_add_c2(a,i,j,c0,c1,c2) \
626         mul_add_c2((a)[i],(a)[j],c0,c1,c2)
627 # endif                         /* !BN_LLONG */
628
629 void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
630 {
631     BN_ULONG c1, c2, c3;
632
633     c1 = 0;
634     c2 = 0;
635     c3 = 0;
636     mul_add_c(a[0], b[0], c1, c2, c3);
637     r[0] = c1;
638     c1 = 0;
639     mul_add_c(a[0], b[1], c2, c3, c1);
640     mul_add_c(a[1], b[0], c2, c3, c1);
641     r[1] = c2;
642     c2 = 0;
643     mul_add_c(a[2], b[0], c3, c1, c2);
644     mul_add_c(a[1], b[1], c3, c1, c2);
645     mul_add_c(a[0], b[2], c3, c1, c2);
646     r[2] = c3;
647     c3 = 0;
648     mul_add_c(a[0], b[3], c1, c2, c3);
649     mul_add_c(a[1], b[2], c1, c2, c3);
650     mul_add_c(a[2], b[1], c1, c2, c3);
651     mul_add_c(a[3], b[0], c1, c2, c3);
652     r[3] = c1;
653     c1 = 0;
654     mul_add_c(a[4], b[0], c2, c3, c1);
655     mul_add_c(a[3], b[1], c2, c3, c1);
656     mul_add_c(a[2], b[2], c2, c3, c1);
657     mul_add_c(a[1], b[3], c2, c3, c1);
658     mul_add_c(a[0], b[4], c2, c3, c1);
659     r[4] = c2;
660     c2 = 0;
661     mul_add_c(a[0], b[5], c3, c1, c2);
662     mul_add_c(a[1], b[4], c3, c1, c2);
663     mul_add_c(a[2], b[3], c3, c1, c2);
664     mul_add_c(a[3], b[2], c3, c1, c2);
665     mul_add_c(a[4], b[1], c3, c1, c2);
666     mul_add_c(a[5], b[0], c3, c1, c2);
667     r[5] = c3;
668     c3 = 0;
669     mul_add_c(a[6], b[0], c1, c2, c3);
670     mul_add_c(a[5], b[1], c1, c2, c3);
671     mul_add_c(a[4], b[2], c1, c2, c3);
672     mul_add_c(a[3], b[3], c1, c2, c3);
673     mul_add_c(a[2], b[4], c1, c2, c3);
674     mul_add_c(a[1], b[5], c1, c2, c3);
675     mul_add_c(a[0], b[6], c1, c2, c3);
676     r[6] = c1;
677     c1 = 0;
678     mul_add_c(a[0], b[7], c2, c3, c1);
679     mul_add_c(a[1], b[6], c2, c3, c1);
680     mul_add_c(a[2], b[5], c2, c3, c1);
681     mul_add_c(a[3], b[4], c2, c3, c1);
682     mul_add_c(a[4], b[3], c2, c3, c1);
683     mul_add_c(a[5], b[2], c2, c3, c1);
684     mul_add_c(a[6], b[1], c2, c3, c1);
685     mul_add_c(a[7], b[0], c2, c3, c1);
686     r[7] = c2;
687     c2 = 0;
688     mul_add_c(a[7], b[1], c3, c1, c2);
689     mul_add_c(a[6], b[2], c3, c1, c2);
690     mul_add_c(a[5], b[3], c3, c1, c2);
691     mul_add_c(a[4], b[4], c3, c1, c2);
692     mul_add_c(a[3], b[5], c3, c1, c2);
693     mul_add_c(a[2], b[6], c3, c1, c2);
694     mul_add_c(a[1], b[7], c3, c1, c2);
695     r[8] = c3;
696     c3 = 0;
697     mul_add_c(a[2], b[7], c1, c2, c3);
698     mul_add_c(a[3], b[6], c1, c2, c3);
699     mul_add_c(a[4], b[5], c1, c2, c3);
700     mul_add_c(a[5], b[4], c1, c2, c3);
701     mul_add_c(a[6], b[3], c1, c2, c3);
702     mul_add_c(a[7], b[2], c1, c2, c3);
703     r[9] = c1;
704     c1 = 0;
705     mul_add_c(a[7], b[3], c2, c3, c1);
706     mul_add_c(a[6], b[4], c2, c3, c1);
707     mul_add_c(a[5], b[5], c2, c3, c1);
708     mul_add_c(a[4], b[6], c2, c3, c1);
709     mul_add_c(a[3], b[7], c2, c3, c1);
710     r[10] = c2;
711     c2 = 0;
712     mul_add_c(a[4], b[7], c3, c1, c2);
713     mul_add_c(a[5], b[6], c3, c1, c2);
714     mul_add_c(a[6], b[5], c3, c1, c2);
715     mul_add_c(a[7], b[4], c3, c1, c2);
716     r[11] = c3;
717     c3 = 0;
718     mul_add_c(a[7], b[5], c1, c2, c3);
719     mul_add_c(a[6], b[6], c1, c2, c3);
720     mul_add_c(a[5], b[7], c1, c2, c3);
721     r[12] = c1;
722     c1 = 0;
723     mul_add_c(a[6], b[7], c2, c3, c1);
724     mul_add_c(a[7], b[6], c2, c3, c1);
725     r[13] = c2;
726     c2 = 0;
727     mul_add_c(a[7], b[7], c3, c1, c2);
728     r[14] = c3;
729     r[15] = c1;
730 }
731
732 void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
733 {
734     BN_ULONG c1, c2, c3;
735
736     c1 = 0;
737     c2 = 0;
738     c3 = 0;
739     mul_add_c(a[0], b[0], c1, c2, c3);
740     r[0] = c1;
741     c1 = 0;
742     mul_add_c(a[0], b[1], c2, c3, c1);
743     mul_add_c(a[1], b[0], c2, c3, c1);
744     r[1] = c2;
745     c2 = 0;
746     mul_add_c(a[2], b[0], c3, c1, c2);
747     mul_add_c(a[1], b[1], c3, c1, c2);
748     mul_add_c(a[0], b[2], c3, c1, c2);
749     r[2] = c3;
750     c3 = 0;
751     mul_add_c(a[0], b[3], c1, c2, c3);
752     mul_add_c(a[1], b[2], c1, c2, c3);
753     mul_add_c(a[2], b[1], c1, c2, c3);
754     mul_add_c(a[3], b[0], c1, c2, c3);
755     r[3] = c1;
756     c1 = 0;
757     mul_add_c(a[3], b[1], c2, c3, c1);
758     mul_add_c(a[2], b[2], c2, c3, c1);
759     mul_add_c(a[1], b[3], c2, c3, c1);
760     r[4] = c2;
761     c2 = 0;
762     mul_add_c(a[2], b[3], c3, c1, c2);
763     mul_add_c(a[3], b[2], c3, c1, c2);
764     r[5] = c3;
765     c3 = 0;
766     mul_add_c(a[3], b[3], c1, c2, c3);
767     r[6] = c1;
768     r[7] = c2;
769 }
770
771 void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
772 {
773     BN_ULONG c1, c2, c3;
774
775     c1 = 0;
776     c2 = 0;
777     c3 = 0;
778     sqr_add_c(a, 0, c1, c2, c3);
779     r[0] = c1;
780     c1 = 0;
781     sqr_add_c2(a, 1, 0, c2, c3, c1);
782     r[1] = c2;
783     c2 = 0;
784     sqr_add_c(a, 1, c3, c1, c2);
785     sqr_add_c2(a, 2, 0, c3, c1, c2);
786     r[2] = c3;
787     c3 = 0;
788     sqr_add_c2(a, 3, 0, c1, c2, c3);
789     sqr_add_c2(a, 2, 1, c1, c2, c3);
790     r[3] = c1;
791     c1 = 0;
792     sqr_add_c(a, 2, c2, c3, c1);
793     sqr_add_c2(a, 3, 1, c2, c3, c1);
794     sqr_add_c2(a, 4, 0, c2, c3, c1);
795     r[4] = c2;
796     c2 = 0;
797     sqr_add_c2(a, 5, 0, c3, c1, c2);
798     sqr_add_c2(a, 4, 1, c3, c1, c2);
799     sqr_add_c2(a, 3, 2, c3, c1, c2);
800     r[5] = c3;
801     c3 = 0;
802     sqr_add_c(a, 3, c1, c2, c3);
803     sqr_add_c2(a, 4, 2, c1, c2, c3);
804     sqr_add_c2(a, 5, 1, c1, c2, c3);
805     sqr_add_c2(a, 6, 0, c1, c2, c3);
806     r[6] = c1;
807     c1 = 0;
808     sqr_add_c2(a, 7, 0, c2, c3, c1);
809     sqr_add_c2(a, 6, 1, c2, c3, c1);
810     sqr_add_c2(a, 5, 2, c2, c3, c1);
811     sqr_add_c2(a, 4, 3, c2, c3, c1);
812     r[7] = c2;
813     c2 = 0;
814     sqr_add_c(a, 4, c3, c1, c2);
815     sqr_add_c2(a, 5, 3, c3, c1, c2);
816     sqr_add_c2(a, 6, 2, c3, c1, c2);
817     sqr_add_c2(a, 7, 1, c3, c1, c2);
818     r[8] = c3;
819     c3 = 0;
820     sqr_add_c2(a, 7, 2, c1, c2, c3);
821     sqr_add_c2(a, 6, 3, c1, c2, c3);
822     sqr_add_c2(a, 5, 4, c1, c2, c3);
823     r[9] = c1;
824     c1 = 0;
825     sqr_add_c(a, 5, c2, c3, c1);
826     sqr_add_c2(a, 6, 4, c2, c3, c1);
827     sqr_add_c2(a, 7, 3, c2, c3, c1);
828     r[10] = c2;
829     c2 = 0;
830     sqr_add_c2(a, 7, 4, c3, c1, c2);
831     sqr_add_c2(a, 6, 5, c3, c1, c2);
832     r[11] = c3;
833     c3 = 0;
834     sqr_add_c(a, 6, c1, c2, c3);
835     sqr_add_c2(a, 7, 5, c1, c2, c3);
836     r[12] = c1;
837     c1 = 0;
838     sqr_add_c2(a, 7, 6, c2, c3, c1);
839     r[13] = c2;
840     c2 = 0;
841     sqr_add_c(a, 7, c3, c1, c2);
842     r[14] = c3;
843     r[15] = c1;
844 }
845
846 void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
847 {
848     BN_ULONG c1, c2, c3;
849
850     c1 = 0;
851     c2 = 0;
852     c3 = 0;
853     sqr_add_c(a, 0, c1, c2, c3);
854     r[0] = c1;
855     c1 = 0;
856     sqr_add_c2(a, 1, 0, c2, c3, c1);
857     r[1] = c2;
858     c2 = 0;
859     sqr_add_c(a, 1, c3, c1, c2);
860     sqr_add_c2(a, 2, 0, c3, c1, c2);
861     r[2] = c3;
862     c3 = 0;
863     sqr_add_c2(a, 3, 0, c1, c2, c3);
864     sqr_add_c2(a, 2, 1, c1, c2, c3);
865     r[3] = c1;
866     c1 = 0;
867     sqr_add_c(a, 2, c2, c3, c1);
868     sqr_add_c2(a, 3, 1, c2, c3, c1);
869     r[4] = c2;
870     c2 = 0;
871     sqr_add_c2(a, 3, 2, c3, c1, c2);
872     r[5] = c3;
873     c3 = 0;
874     sqr_add_c(a, 3, c1, c2, c3);
875     r[6] = c1;
876     r[7] = c2;
877 }
878
879 # ifdef OPENSSL_NO_ASM
880 #  ifdef OPENSSL_BN_ASM_MONT
881 #   include <alloca.h>
882 /*
883  * This is essentially reference implementation, which may or may not
884  * result in performance improvement. E.g. on IA-32 this routine was
885  * observed to give 40% faster rsa1024 private key operations and 10%
886  * faster rsa4096 ones, while on AMD64 it improves rsa1024 sign only
887  * by 10% and *worsens* rsa4096 sign by 15%. Once again, it's a
888  * reference implementation, one to be used as starting point for
889  * platform-specific assembler. Mentioned numbers apply to compiler
890  * generated code compiled with and without -DOPENSSL_BN_ASM_MONT and
891  * can vary not only from platform to platform, but even for compiler
892  * versions. Assembler vs. assembler improvement coefficients can
893  * [and are known to] differ and are to be documented elsewhere.
894  */
895 int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
896                 const BN_ULONG *np, const BN_ULONG *n0p, int num)
897 {
898     BN_ULONG c0, c1, ml, *tp, n0;
899 #   ifdef mul64
900     BN_ULONG mh;
901 #   endif
902     volatile BN_ULONG *vp;
903     int i = 0, j;
904
905 #   if 0                        /* template for platform-specific
906                                  * implementation */
907     if (ap == bp)
908         return bn_sqr_mont(rp, ap, np, n0p, num);
909 #   endif
910     vp = tp = alloca((num + 2) * sizeof(BN_ULONG));
911
912     n0 = *n0p;
913
914     c0 = 0;
915     ml = bp[0];
916 #   ifdef mul64
917     mh = HBITS(ml);
918     ml = LBITS(ml);
919     for (j = 0; j < num; ++j)
920         mul(tp[j], ap[j], ml, mh, c0);
921 #   else
922     for (j = 0; j < num; ++j)
923         mul(tp[j], ap[j], ml, c0);
924 #   endif
925
926     tp[num] = c0;
927     tp[num + 1] = 0;
928     goto enter;
929
930     for (i = 0; i < num; i++) {
931         c0 = 0;
932         ml = bp[i];
933 #   ifdef mul64
934         mh = HBITS(ml);
935         ml = LBITS(ml);
936         for (j = 0; j < num; ++j)
937             mul_add(tp[j], ap[j], ml, mh, c0);
938 #   else
939         for (j = 0; j < num; ++j)
940             mul_add(tp[j], ap[j], ml, c0);
941 #   endif
942         c1 = (tp[num] + c0) & BN_MASK2;
943         tp[num] = c1;
944         tp[num + 1] = (c1 < c0 ? 1 : 0);
945  enter:
946         c1 = tp[0];
947         ml = (c1 * n0) & BN_MASK2;
948         c0 = 0;
949 #   ifdef mul64
950         mh = HBITS(ml);
951         ml = LBITS(ml);
952         mul_add(c1, np[0], ml, mh, c0);
953 #   else
954         mul_add(c1, ml, np[0], c0);
955 #   endif
956         for (j = 1; j < num; j++) {
957             c1 = tp[j];
958 #   ifdef mul64
959             mul_add(c1, np[j], ml, mh, c0);
960 #   else
961             mul_add(c1, ml, np[j], c0);
962 #   endif
963             tp[j - 1] = c1 & BN_MASK2;
964         }
965         c1 = (tp[num] + c0) & BN_MASK2;
966         tp[num - 1] = c1;
967         tp[num] = tp[num + 1] + (c1 < c0 ? 1 : 0);
968     }
969
970     if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {
971         c0 = bn_sub_words(rp, tp, np, num);
972         if (tp[num] != 0 || c0 == 0) {
973             for (i = 0; i < num + 2; i++)
974                 vp[i] = 0;
975             return 1;
976         }
977     }
978     for (i = 0; i < num; i++)
979         rp[i] = tp[i], vp[i] = 0;
980     vp[num] = 0;
981     vp[num + 1] = 0;
982     return 1;
983 }
984 #  else
985 /*
986  * Return value of 0 indicates that multiplication/convolution was not
987  * performed to signal the caller to fall down to alternative/original
988  * code-path.
989  */
990 int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
991                 const BN_ULONG *np, const BN_ULONG *n0, int num)
992 {
993     return 0;
994 }
995 #  endif                        /* OPENSSL_BN_ASM_MONT */
996 # endif
997
998 #else                           /* !BN_MUL_COMBA */
999
1000 /* hmm... is it faster just to do a multiply? */
1001 # undef bn_sqr_comba4
1002 # undef bn_sqr_comba8
1003 void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
1004 {
1005     BN_ULONG t[8];
1006     bn_sqr_normal(r, a, 4, t);
1007 }
1008
1009 void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
1010 {
1011     BN_ULONG t[16];
1012     bn_sqr_normal(r, a, 8, t);
1013 }
1014
1015 void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
1016 {
1017     r[4] = bn_mul_words(&(r[0]), a, 4, b[0]);
1018     r[5] = bn_mul_add_words(&(r[1]), a, 4, b[1]);
1019     r[6] = bn_mul_add_words(&(r[2]), a, 4, b[2]);
1020     r[7] = bn_mul_add_words(&(r[3]), a, 4, b[3]);
1021 }
1022
1023 void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
1024 {
1025     r[8] = bn_mul_words(&(r[0]), a, 8, b[0]);
1026     r[9] = bn_mul_add_words(&(r[1]), a, 8, b[1]);
1027     r[10] = bn_mul_add_words(&(r[2]), a, 8, b[2]);
1028     r[11] = bn_mul_add_words(&(r[3]), a, 8, b[3]);
1029     r[12] = bn_mul_add_words(&(r[4]), a, 8, b[4]);
1030     r[13] = bn_mul_add_words(&(r[5]), a, 8, b[5]);
1031     r[14] = bn_mul_add_words(&(r[6]), a, 8, b[6]);
1032     r[15] = bn_mul_add_words(&(r[7]), a, 8, b[7]);
1033 }
1034
1035 # ifdef OPENSSL_NO_ASM
1036 #  ifdef OPENSSL_BN_ASM_MONT
1037 #   include <alloca.h>
1038 int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
1039                 const BN_ULONG *np, const BN_ULONG *n0p, int num)
1040 {
1041     BN_ULONG c0, c1, *tp, n0 = *n0p;
1042     volatile BN_ULONG *vp;
1043     int i = 0, j;
1044
1045     vp = tp = alloca((num + 2) * sizeof(BN_ULONG));
1046
1047     for (i = 0; i <= num; i++)
1048         tp[i] = 0;
1049
1050     for (i = 0; i < num; i++) {
1051         c0 = bn_mul_add_words(tp, ap, num, bp[i]);
1052         c1 = (tp[num] + c0) & BN_MASK2;
1053         tp[num] = c1;
1054         tp[num + 1] = (c1 < c0 ? 1 : 0);
1055
1056         c0 = bn_mul_add_words(tp, np, num, tp[0] * n0);
1057         c1 = (tp[num] + c0) & BN_MASK2;
1058         tp[num] = c1;
1059         tp[num + 1] += (c1 < c0 ? 1 : 0);
1060         for (j = 0; j <= num; j++)
1061             tp[j] = tp[j + 1];
1062     }
1063
1064     if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {
1065         c0 = bn_sub_words(rp, tp, np, num);
1066         if (tp[num] != 0 || c0 == 0) {
1067             for (i = 0; i < num + 2; i++)
1068                 vp[i] = 0;
1069             return 1;
1070         }
1071     }
1072     for (i = 0; i < num; i++)
1073         rp[i] = tp[i], vp[i] = 0;
1074     vp[num] = 0;
1075     vp[num + 1] = 0;
1076     return 1;
1077 }
1078 #  else
1079 int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
1080                 const BN_ULONG *np, const BN_ULONG *n0, int num)
1081 {
1082     return 0;
1083 }
1084 #  endif                        /* OPENSSL_BN_ASM_MONT */
1085 # endif
1086
1087 #endif                          /* !BN_MUL_COMBA */