tip(1): Fix various warnings and errors emitted by clang
[dragonfly.git] / crypto / openssl / crypto / bn / asm / x86_64-gcc.c
1 #include "../bn_lcl.h"
2 #if !(defined(__GNUC__) && __GNUC__>=2)
3 # include "../bn_asm.c" /* kind of dirty hack for Sun Studio */
4 #else
5 /*
6  * x86_64 BIGNUM accelerator version 0.1, December 2002.
7  *
8  * Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
9  * project.
10  *
11  * Rights for redistribution and usage in source and binary forms are
12  * granted according to the OpenSSL license. Warranty of any kind is
13  * disclaimed.
14  *
15  * Q. Version 0.1? It doesn't sound like Andy, he used to assign real
16  *    versions, like 1.0...
17  * A. Well, that's because this code is basically a quick-n-dirty
18  *    proof-of-concept hack. As you can see it's implemented with
19  *    inline assembler, which means that you're bound to GCC and that
20  *    there might be enough room for further improvement.
21  *
22  * Q. Why inline assembler?
23  * A. x86_64 features own ABI which I'm not familiar with. This is
24  *    why I decided to let the compiler take care of subroutine
25  *    prologue/epilogue as well as register allocation. For reference.
26  *    Win64 implements different ABI for AMD64, different from Linux.
27  *
28  * Q. How much faster does it get?
29  * A. 'apps/openssl speed rsa dsa' output with no-asm:
30  *
31  *                        sign    verify    sign/s verify/s
32  *      rsa  512 bits   0.0006s   0.0001s   1683.8  18456.2
33  *      rsa 1024 bits   0.0028s   0.0002s    356.0   6407.0
34  *      rsa 2048 bits   0.0172s   0.0005s     58.0   1957.8
35  *      rsa 4096 bits   0.1155s   0.0018s      8.7    555.6
36  *                        sign    verify    sign/s verify/s
37  *      dsa  512 bits   0.0005s   0.0006s   2100.8   1768.3
38  *      dsa 1024 bits   0.0014s   0.0018s    692.3    559.2
39  *      dsa 2048 bits   0.0049s   0.0061s    204.7    165.0
40  *
41  *    'apps/openssl speed rsa dsa' output with this module:
42  *
43  *                        sign    verify    sign/s verify/s
44  *      rsa  512 bits   0.0004s   0.0000s   2767.1  33297.9
45  *      rsa 1024 bits   0.0012s   0.0001s    867.4  14674.7
46  *      rsa 2048 bits   0.0061s   0.0002s    164.0   5270.0
47  *      rsa 4096 bits   0.0384s   0.0006s     26.1   1650.8
48  *                        sign    verify    sign/s verify/s
49  *      dsa  512 bits   0.0002s   0.0003s   4442.2   3786.3
50  *      dsa 1024 bits   0.0005s   0.0007s   1835.1   1497.4
51  *      dsa 2048 bits   0.0016s   0.0020s    620.4    504.6
52  *
53  *    For the reference. IA-32 assembler implementation performs
54  *    very much like 64-bit code compiled with no-asm on the same
55  *    machine.
56  */
57
58 #ifdef _WIN64
59 #define BN_ULONG unsigned long long
60 #else
61 #define BN_ULONG unsigned long
62 #endif
63
64 #undef mul
65 #undef mul_add
66 #undef sqr
67
68 /*
69  * "m"(a), "+m"(r)      is the way to favor DirectPath ยต-code;
70  * "g"(0)               let the compiler to decide where does it
71  *                      want to keep the value of zero;
72  */
73 #define mul_add(r,a,word,carry) do {    \
74         register BN_ULONG high,low;     \
75         asm ("mulq %3"                  \
76                 : "=a"(low),"=d"(high)  \
77                 : "a"(word),"m"(a)      \
78                 : "cc");                \
79         asm ("addq %2,%0; adcq %3,%1"   \
80                 : "+r"(carry),"+d"(high)\
81                 : "a"(low),"g"(0)       \
82                 : "cc");                \
83         asm ("addq %2,%0; adcq %3,%1"   \
84                 : "+m"(r),"+d"(high)    \
85                 : "r"(carry),"g"(0)     \
86                 : "cc");                \
87         carry=high;                     \
88         } while (0)
89
90 #define mul(r,a,word,carry) do {        \
91         register BN_ULONG high,low;     \
92         asm ("mulq %3"                  \
93                 : "=a"(low),"=d"(high)  \
94                 : "a"(word),"g"(a)      \
95                 : "cc");                \
96         asm ("addq %2,%0; adcq %3,%1"   \
97                 : "+r"(carry),"+d"(high)\
98                 : "a"(low),"g"(0)       \
99                 : "cc");                \
100         (r)=carry, carry=high;          \
101         } while (0)
102
103 #define sqr(r0,r1,a)                    \
104         asm ("mulq %2"                  \
105                 : "=a"(r0),"=d"(r1)     \
106                 : "a"(a)                \
107                 : "cc");
108
109 BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
110         {
111         BN_ULONG c1=0;
112
113         if (num <= 0) return(c1);
114
115         while (num&~3)
116                 {
117                 mul_add(rp[0],ap[0],w,c1);
118                 mul_add(rp[1],ap[1],w,c1);
119                 mul_add(rp[2],ap[2],w,c1);
120                 mul_add(rp[3],ap[3],w,c1);
121                 ap+=4; rp+=4; num-=4;
122                 }
123         if (num)
124                 {
125                 mul_add(rp[0],ap[0],w,c1); if (--num==0) return c1;
126                 mul_add(rp[1],ap[1],w,c1); if (--num==0) return c1;
127                 mul_add(rp[2],ap[2],w,c1); return c1;
128                 }
129         
130         return(c1);
131         } 
132
133 BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
134         {
135         BN_ULONG c1=0;
136
137         if (num <= 0) return(c1);
138
139         while (num&~3)
140                 {
141                 mul(rp[0],ap[0],w,c1);
142                 mul(rp[1],ap[1],w,c1);
143                 mul(rp[2],ap[2],w,c1);
144                 mul(rp[3],ap[3],w,c1);
145                 ap+=4; rp+=4; num-=4;
146                 }
147         if (num)
148                 {
149                 mul(rp[0],ap[0],w,c1); if (--num == 0) return c1;
150                 mul(rp[1],ap[1],w,c1); if (--num == 0) return c1;
151                 mul(rp[2],ap[2],w,c1);
152                 }
153         return(c1);
154         } 
155
156 void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
157         {
158         if (n <= 0) return;
159
160         while (n&~3)
161                 {
162                 sqr(r[0],r[1],a[0]);
163                 sqr(r[2],r[3],a[1]);
164                 sqr(r[4],r[5],a[2]);
165                 sqr(r[6],r[7],a[3]);
166                 a+=4; r+=8; n-=4;
167                 }
168         if (n)
169                 {
170                 sqr(r[0],r[1],a[0]); if (--n == 0) return;
171                 sqr(r[2],r[3],a[1]); if (--n == 0) return;
172                 sqr(r[4],r[5],a[2]);
173                 }
174         }
175
176 BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
177 {       BN_ULONG ret,waste;
178
179         asm ("divq      %4"
180                 : "=a"(ret),"=d"(waste)
181                 : "a"(l),"d"(h),"g"(d)
182                 : "cc");
183
184         return ret;
185 }
186
187 BN_ULONG bn_add_words (BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int n)
188 { BN_ULONG ret=0,i=0;
189
190         if (n <= 0) return 0;
191
192         asm (
193         "       subq    %2,%2           \n"
194         ".p2align 4                     \n"
195         "1:     movq    (%4,%2,8),%0    \n"
196         "       adcq    (%5,%2,8),%0    \n"
197         "       movq    %0,(%3,%2,8)    \n"
198         "       leaq    1(%2),%2        \n"
199         "       loop    1b              \n"
200         "       sbbq    %0,%0           \n"
201                 : "=&a"(ret),"+c"(n),"=&r"(i)
202                 : "r"(rp),"r"(ap),"r"(bp)
203                 : "cc"
204         );
205
206   return ret&1;
207 }
208
209 #ifndef SIMICS
210 BN_ULONG bn_sub_words (BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int n)
211 { BN_ULONG ret=0,i=0;
212
213         if (n <= 0) return 0;
214
215         asm (
216         "       subq    %2,%2           \n"
217         ".p2align 4                     \n"
218         "1:     movq    (%4,%2,8),%0    \n"
219         "       sbbq    (%5,%2,8),%0    \n"
220         "       movq    %0,(%3,%2,8)    \n"
221         "       leaq    1(%2),%2        \n"
222         "       loop    1b              \n"
223         "       sbbq    %0,%0           \n"
224                 : "=&a"(ret),"+c"(n),"=&r"(i)
225                 : "r"(rp),"r"(ap),"r"(bp)
226                 : "cc"
227         );
228
229   return ret&1;
230 }
231 #else
232 /* Simics 1.4<7 has buggy sbbq:-( */
233 #define BN_MASK2 0xffffffffffffffffL
234 BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
235         {
236         BN_ULONG t1,t2;
237         int c=0;
238
239         if (n <= 0) return((BN_ULONG)0);
240
241         for (;;)
242                 {
243                 t1=a[0]; t2=b[0];
244                 r[0]=(t1-t2-c)&BN_MASK2;
245                 if (t1 != t2) c=(t1 < t2);
246                 if (--n <= 0) break;
247
248                 t1=a[1]; t2=b[1];
249                 r[1]=(t1-t2-c)&BN_MASK2;
250                 if (t1 != t2) c=(t1 < t2);
251                 if (--n <= 0) break;
252
253                 t1=a[2]; t2=b[2];
254                 r[2]=(t1-t2-c)&BN_MASK2;
255                 if (t1 != t2) c=(t1 < t2);
256                 if (--n <= 0) break;
257
258                 t1=a[3]; t2=b[3];
259                 r[3]=(t1-t2-c)&BN_MASK2;
260                 if (t1 != t2) c=(t1 < t2);
261                 if (--n <= 0) break;
262
263                 a+=4;
264                 b+=4;
265                 r+=4;
266                 }
267         return(c);
268         }
269 #endif
270
271 /* mul_add_c(a,b,c0,c1,c2)  -- c+=a*b for three word number c=(c2,c1,c0) */
272 /* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
273 /* sqr_add_c(a,i,c0,c1,c2)  -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
274 /* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */
275
276 #if 0
277 /* original macros are kept for reference purposes */
278 #define mul_add_c(a,b,c0,c1,c2) {       \
279         BN_ULONG ta=(a),tb=(b);         \
280         t1 = ta * tb;                   \
281         t2 = BN_UMULT_HIGH(ta,tb);      \
282         c0 += t1; t2 += (c0<t1)?1:0;    \
283         c1 += t2; c2 += (c1<t2)?1:0;    \
284         }
285
286 #define mul_add_c2(a,b,c0,c1,c2) {      \
287         BN_ULONG ta=(a),tb=(b),t0;      \
288         t1 = BN_UMULT_HIGH(ta,tb);      \
289         t0 = ta * tb;                   \
290         t2 = t1+t1; c2 += (t2<t1)?1:0;  \
291         t1 = t0+t0; t2 += (t1<t0)?1:0;  \
292         c0 += t1; t2 += (c0<t1)?1:0;    \
293         c1 += t2; c2 += (c1<t2)?1:0;    \
294         }
295 #else
296 #define mul_add_c(a,b,c0,c1,c2) do {    \
297         asm ("mulq %3"                  \
298                 : "=a"(t1),"=d"(t2)     \
299                 : "a"(a),"m"(b)         \
300                 : "cc");                \
301         asm ("addq %2,%0; adcq %3,%1"   \
302                 : "+r"(c0),"+d"(t2)     \
303                 : "a"(t1),"g"(0)        \
304                 : "cc");                \
305         asm ("addq %2,%0; adcq %3,%1"   \
306                 : "+r"(c1),"+r"(c2)     \
307                 : "d"(t2),"g"(0)        \
308                 : "cc");                \
309         } while (0)
310
311 #define sqr_add_c(a,i,c0,c1,c2) do {    \
312         asm ("mulq %2"                  \
313                 : "=a"(t1),"=d"(t2)     \
314                 : "a"(a[i])             \
315                 : "cc");                \
316         asm ("addq %2,%0; adcq %3,%1"   \
317                 : "+r"(c0),"+d"(t2)     \
318                 : "a"(t1),"g"(0)        \
319                 : "cc");                \
320         asm ("addq %2,%0; adcq %3,%1"   \
321                 : "+r"(c1),"+r"(c2)     \
322                 : "d"(t2),"g"(0)        \
323                 : "cc");                \
324         } while (0)
325
326 #define mul_add_c2(a,b,c0,c1,c2) do {   \
327         asm ("mulq %3"                  \
328                 : "=a"(t1),"=d"(t2)     \
329                 : "a"(a),"m"(b)         \
330                 : "cc");                \
331         asm ("addq %0,%0; adcq %2,%1"   \
332                 : "+d"(t2),"+r"(c2)     \
333                 : "g"(0)                \
334                 : "cc");                \
335         asm ("addq %0,%0; adcq %2,%1"   \
336                 : "+a"(t1),"+d"(t2)     \
337                 : "g"(0)                \
338                 : "cc");                \
339         asm ("addq %2,%0; adcq %3,%1"   \
340                 : "+r"(c0),"+d"(t2)     \
341                 : "a"(t1),"g"(0)        \
342                 : "cc");                \
343         asm ("addq %2,%0; adcq %3,%1"   \
344                 : "+r"(c1),"+r"(c2)     \
345                 : "d"(t2),"g"(0)        \
346                 : "cc");                \
347         } while (0)
348 #endif
349
350 #define sqr_add_c2(a,i,j,c0,c1,c2)      \
351         mul_add_c2((a)[i],(a)[j],c0,c1,c2)
352
353 void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
354         {
355         BN_ULONG t1,t2;
356         BN_ULONG c1,c2,c3;
357
358         c1=0;
359         c2=0;
360         c3=0;
361         mul_add_c(a[0],b[0],c1,c2,c3);
362         r[0]=c1;
363         c1=0;
364         mul_add_c(a[0],b[1],c2,c3,c1);
365         mul_add_c(a[1],b[0],c2,c3,c1);
366         r[1]=c2;
367         c2=0;
368         mul_add_c(a[2],b[0],c3,c1,c2);
369         mul_add_c(a[1],b[1],c3,c1,c2);
370         mul_add_c(a[0],b[2],c3,c1,c2);
371         r[2]=c3;
372         c3=0;
373         mul_add_c(a[0],b[3],c1,c2,c3);
374         mul_add_c(a[1],b[2],c1,c2,c3);
375         mul_add_c(a[2],b[1],c1,c2,c3);
376         mul_add_c(a[3],b[0],c1,c2,c3);
377         r[3]=c1;
378         c1=0;
379         mul_add_c(a[4],b[0],c2,c3,c1);
380         mul_add_c(a[3],b[1],c2,c3,c1);
381         mul_add_c(a[2],b[2],c2,c3,c1);
382         mul_add_c(a[1],b[3],c2,c3,c1);
383         mul_add_c(a[0],b[4],c2,c3,c1);
384         r[4]=c2;
385         c2=0;
386         mul_add_c(a[0],b[5],c3,c1,c2);
387         mul_add_c(a[1],b[4],c3,c1,c2);
388         mul_add_c(a[2],b[3],c3,c1,c2);
389         mul_add_c(a[3],b[2],c3,c1,c2);
390         mul_add_c(a[4],b[1],c3,c1,c2);
391         mul_add_c(a[5],b[0],c3,c1,c2);
392         r[5]=c3;
393         c3=0;
394         mul_add_c(a[6],b[0],c1,c2,c3);
395         mul_add_c(a[5],b[1],c1,c2,c3);
396         mul_add_c(a[4],b[2],c1,c2,c3);
397         mul_add_c(a[3],b[3],c1,c2,c3);
398         mul_add_c(a[2],b[4],c1,c2,c3);
399         mul_add_c(a[1],b[5],c1,c2,c3);
400         mul_add_c(a[0],b[6],c1,c2,c3);
401         r[6]=c1;
402         c1=0;
403         mul_add_c(a[0],b[7],c2,c3,c1);
404         mul_add_c(a[1],b[6],c2,c3,c1);
405         mul_add_c(a[2],b[5],c2,c3,c1);
406         mul_add_c(a[3],b[4],c2,c3,c1);
407         mul_add_c(a[4],b[3],c2,c3,c1);
408         mul_add_c(a[5],b[2],c2,c3,c1);
409         mul_add_c(a[6],b[1],c2,c3,c1);
410         mul_add_c(a[7],b[0],c2,c3,c1);
411         r[7]=c2;
412         c2=0;
413         mul_add_c(a[7],b[1],c3,c1,c2);
414         mul_add_c(a[6],b[2],c3,c1,c2);
415         mul_add_c(a[5],b[3],c3,c1,c2);
416         mul_add_c(a[4],b[4],c3,c1,c2);
417         mul_add_c(a[3],b[5],c3,c1,c2);
418         mul_add_c(a[2],b[6],c3,c1,c2);
419         mul_add_c(a[1],b[7],c3,c1,c2);
420         r[8]=c3;
421         c3=0;
422         mul_add_c(a[2],b[7],c1,c2,c3);
423         mul_add_c(a[3],b[6],c1,c2,c3);
424         mul_add_c(a[4],b[5],c1,c2,c3);
425         mul_add_c(a[5],b[4],c1,c2,c3);
426         mul_add_c(a[6],b[3],c1,c2,c3);
427         mul_add_c(a[7],b[2],c1,c2,c3);
428         r[9]=c1;
429         c1=0;
430         mul_add_c(a[7],b[3],c2,c3,c1);
431         mul_add_c(a[6],b[4],c2,c3,c1);
432         mul_add_c(a[5],b[5],c2,c3,c1);
433         mul_add_c(a[4],b[6],c2,c3,c1);
434         mul_add_c(a[3],b[7],c2,c3,c1);
435         r[10]=c2;
436         c2=0;
437         mul_add_c(a[4],b[7],c3,c1,c2);
438         mul_add_c(a[5],b[6],c3,c1,c2);
439         mul_add_c(a[6],b[5],c3,c1,c2);
440         mul_add_c(a[7],b[4],c3,c1,c2);
441         r[11]=c3;
442         c3=0;
443         mul_add_c(a[7],b[5],c1,c2,c3);
444         mul_add_c(a[6],b[6],c1,c2,c3);
445         mul_add_c(a[5],b[7],c1,c2,c3);
446         r[12]=c1;
447         c1=0;
448         mul_add_c(a[6],b[7],c2,c3,c1);
449         mul_add_c(a[7],b[6],c2,c3,c1);
450         r[13]=c2;
451         c2=0;
452         mul_add_c(a[7],b[7],c3,c1,c2);
453         r[14]=c3;
454         r[15]=c1;
455         }
456
457 void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
458         {
459         BN_ULONG t1,t2;
460         BN_ULONG c1,c2,c3;
461
462         c1=0;
463         c2=0;
464         c3=0;
465         mul_add_c(a[0],b[0],c1,c2,c3);
466         r[0]=c1;
467         c1=0;
468         mul_add_c(a[0],b[1],c2,c3,c1);
469         mul_add_c(a[1],b[0],c2,c3,c1);
470         r[1]=c2;
471         c2=0;
472         mul_add_c(a[2],b[0],c3,c1,c2);
473         mul_add_c(a[1],b[1],c3,c1,c2);
474         mul_add_c(a[0],b[2],c3,c1,c2);
475         r[2]=c3;
476         c3=0;
477         mul_add_c(a[0],b[3],c1,c2,c3);
478         mul_add_c(a[1],b[2],c1,c2,c3);
479         mul_add_c(a[2],b[1],c1,c2,c3);
480         mul_add_c(a[3],b[0],c1,c2,c3);
481         r[3]=c1;
482         c1=0;
483         mul_add_c(a[3],b[1],c2,c3,c1);
484         mul_add_c(a[2],b[2],c2,c3,c1);
485         mul_add_c(a[1],b[3],c2,c3,c1);
486         r[4]=c2;
487         c2=0;
488         mul_add_c(a[2],b[3],c3,c1,c2);
489         mul_add_c(a[3],b[2],c3,c1,c2);
490         r[5]=c3;
491         c3=0;
492         mul_add_c(a[3],b[3],c1,c2,c3);
493         r[6]=c1;
494         r[7]=c2;
495         }
496
497 void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
498         {
499         BN_ULONG t1,t2;
500         BN_ULONG c1,c2,c3;
501
502         c1=0;
503         c2=0;
504         c3=0;
505         sqr_add_c(a,0,c1,c2,c3);
506         r[0]=c1;
507         c1=0;
508         sqr_add_c2(a,1,0,c2,c3,c1);
509         r[1]=c2;
510         c2=0;
511         sqr_add_c(a,1,c3,c1,c2);
512         sqr_add_c2(a,2,0,c3,c1,c2);
513         r[2]=c3;
514         c3=0;
515         sqr_add_c2(a,3,0,c1,c2,c3);
516         sqr_add_c2(a,2,1,c1,c2,c3);
517         r[3]=c1;
518         c1=0;
519         sqr_add_c(a,2,c2,c3,c1);
520         sqr_add_c2(a,3,1,c2,c3,c1);
521         sqr_add_c2(a,4,0,c2,c3,c1);
522         r[4]=c2;
523         c2=0;
524         sqr_add_c2(a,5,0,c3,c1,c2);
525         sqr_add_c2(a,4,1,c3,c1,c2);
526         sqr_add_c2(a,3,2,c3,c1,c2);
527         r[5]=c3;
528         c3=0;
529         sqr_add_c(a,3,c1,c2,c3);
530         sqr_add_c2(a,4,2,c1,c2,c3);
531         sqr_add_c2(a,5,1,c1,c2,c3);
532         sqr_add_c2(a,6,0,c1,c2,c3);
533         r[6]=c1;
534         c1=0;
535         sqr_add_c2(a,7,0,c2,c3,c1);
536         sqr_add_c2(a,6,1,c2,c3,c1);
537         sqr_add_c2(a,5,2,c2,c3,c1);
538         sqr_add_c2(a,4,3,c2,c3,c1);
539         r[7]=c2;
540         c2=0;
541         sqr_add_c(a,4,c3,c1,c2);
542         sqr_add_c2(a,5,3,c3,c1,c2);
543         sqr_add_c2(a,6,2,c3,c1,c2);
544         sqr_add_c2(a,7,1,c3,c1,c2);
545         r[8]=c3;
546         c3=0;
547         sqr_add_c2(a,7,2,c1,c2,c3);
548         sqr_add_c2(a,6,3,c1,c2,c3);
549         sqr_add_c2(a,5,4,c1,c2,c3);
550         r[9]=c1;
551         c1=0;
552         sqr_add_c(a,5,c2,c3,c1);
553         sqr_add_c2(a,6,4,c2,c3,c1);
554         sqr_add_c2(a,7,3,c2,c3,c1);
555         r[10]=c2;
556         c2=0;
557         sqr_add_c2(a,7,4,c3,c1,c2);
558         sqr_add_c2(a,6,5,c3,c1,c2);
559         r[11]=c3;
560         c3=0;
561         sqr_add_c(a,6,c1,c2,c3);
562         sqr_add_c2(a,7,5,c1,c2,c3);
563         r[12]=c1;
564         c1=0;
565         sqr_add_c2(a,7,6,c2,c3,c1);
566         r[13]=c2;
567         c2=0;
568         sqr_add_c(a,7,c3,c1,c2);
569         r[14]=c3;
570         r[15]=c1;
571         }
572
573 void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
574         {
575         BN_ULONG t1,t2;
576         BN_ULONG c1,c2,c3;
577
578         c1=0;
579         c2=0;
580         c3=0;
581         sqr_add_c(a,0,c1,c2,c3);
582         r[0]=c1;
583         c1=0;
584         sqr_add_c2(a,1,0,c2,c3,c1);
585         r[1]=c2;
586         c2=0;
587         sqr_add_c(a,1,c3,c1,c2);
588         sqr_add_c2(a,2,0,c3,c1,c2);
589         r[2]=c3;
590         c3=0;
591         sqr_add_c2(a,3,0,c1,c2,c3);
592         sqr_add_c2(a,2,1,c1,c2,c3);
593         r[3]=c1;
594         c1=0;
595         sqr_add_c(a,2,c2,c3,c1);
596         sqr_add_c2(a,3,1,c2,c3,c1);
597         r[4]=c2;
598         c2=0;
599         sqr_add_c2(a,3,2,c3,c1,c2);
600         r[5]=c3;
601         c3=0;
602         sqr_add_c(a,3,c1,c2,c3);
603         r[6]=c1;
604         r[7]=c2;
605         }
606 #endif