~ubuntu-branches/ubuntu/precise/openssl098/precise

« back to all changes in this revision

Viewing changes to crypto/bn/asm/x86_64-gcc.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2011-03-23 19:50:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110323195031-6h9crj4bymhhr8b8
Tags: upstream-0.9.8o
ImportĀ upstreamĀ versionĀ 0.9.8o

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "../bn_lcl.h"
 
2
#ifdef __SUNPRO_C
 
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
#define BN_ULONG unsigned long
 
59
 
 
60
#undef mul
 
61
#undef mul_add
 
62
#undef sqr
 
63
 
 
64
/*
 
65
 * "m"(a), "+m"(r)      is the way to favor DirectPath ļæ½-code;
 
66
 * "g"(0)               let the compiler to decide where does it
 
67
 *                      want to keep the value of zero;
 
68
 */
 
69
#define mul_add(r,a,word,carry) do {    \
 
70
        register BN_ULONG high,low;     \
 
71
        asm ("mulq %3"                  \
 
72
                : "=a"(low),"=d"(high)  \
 
73
                : "a"(word),"m"(a)      \
 
74
                : "cc");                \
 
75
        asm ("addq %2,%0; adcq %3,%1"   \
 
76
                : "+r"(carry),"+d"(high)\
 
77
                : "a"(low),"g"(0)       \
 
78
                : "cc");                \
 
79
        asm ("addq %2,%0; adcq %3,%1"   \
 
80
                : "+m"(r),"+d"(high)    \
 
81
                : "r"(carry),"g"(0)     \
 
82
                : "cc");                \
 
83
        carry=high;                     \
 
84
        } while (0)
 
85
 
 
86
#define mul(r,a,word,carry) do {        \
 
87
        register BN_ULONG high,low;     \
 
88
        asm ("mulq %3"                  \
 
89
                : "=a"(low),"=d"(high)  \
 
90
                : "a"(word),"g"(a)      \
 
91
                : "cc");                \
 
92
        asm ("addq %2,%0; adcq %3,%1"   \
 
93
                : "+r"(carry),"+d"(high)\
 
94
                : "a"(low),"g"(0)       \
 
95
                : "cc");                \
 
96
        (r)=carry, carry=high;          \
 
97
        } while (0)
 
98
 
 
99
#define sqr(r0,r1,a)                    \
 
100
        asm ("mulq %2"                  \
 
101
                : "=a"(r0),"=d"(r1)     \
 
102
                : "a"(a)                \
 
103
                : "cc");
 
104
 
 
105
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
 
106
        {
 
107
        BN_ULONG c1=0;
 
108
 
 
109
        if (num <= 0) return(c1);
 
110
 
 
111
        while (num&~3)
 
112
                {
 
113
                mul_add(rp[0],ap[0],w,c1);
 
114
                mul_add(rp[1],ap[1],w,c1);
 
115
                mul_add(rp[2],ap[2],w,c1);
 
116
                mul_add(rp[3],ap[3],w,c1);
 
117
                ap+=4; rp+=4; num-=4;
 
118
                }
 
119
        if (num)
 
120
                {
 
121
                mul_add(rp[0],ap[0],w,c1); if (--num==0) return c1;
 
122
                mul_add(rp[1],ap[1],w,c1); if (--num==0) return c1;
 
123
                mul_add(rp[2],ap[2],w,c1); return c1;
 
124
                }
 
125
        
 
126
        return(c1);
 
127
        } 
 
128
 
 
129
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
 
130
        {
 
131
        BN_ULONG c1=0;
 
132
 
 
133
        if (num <= 0) return(c1);
 
134
 
 
135
        while (num&~3)
 
136
                {
 
137
                mul(rp[0],ap[0],w,c1);
 
138
                mul(rp[1],ap[1],w,c1);
 
139
                mul(rp[2],ap[2],w,c1);
 
140
                mul(rp[3],ap[3],w,c1);
 
141
                ap+=4; rp+=4; num-=4;
 
142
                }
 
143
        if (num)
 
144
                {
 
145
                mul(rp[0],ap[0],w,c1); if (--num == 0) return c1;
 
146
                mul(rp[1],ap[1],w,c1); if (--num == 0) return c1;
 
147
                mul(rp[2],ap[2],w,c1);
 
148
                }
 
149
        return(c1);
 
150
        } 
 
151
 
 
152
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
 
153
        {
 
154
        if (n <= 0) return;
 
155
 
 
156
        while (n&~3)
 
157
                {
 
158
                sqr(r[0],r[1],a[0]);
 
159
                sqr(r[2],r[3],a[1]);
 
160
                sqr(r[4],r[5],a[2]);
 
161
                sqr(r[6],r[7],a[3]);
 
162
                a+=4; r+=8; n-=4;
 
163
                }
 
164
        if (n)
 
165
                {
 
166
                sqr(r[0],r[1],a[0]); if (--n == 0) return;
 
167
                sqr(r[2],r[3],a[1]); if (--n == 0) return;
 
168
                sqr(r[4],r[5],a[2]);
 
169
                }
 
170
        }
 
171
 
 
172
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
 
173
{       BN_ULONG ret,waste;
 
174
 
 
175
        asm ("divq      %4"
 
176
                : "=a"(ret),"=d"(waste)
 
177
                : "a"(l),"d"(h),"g"(d)
 
178
                : "cc");
 
179
 
 
180
        return ret;
 
181
}
 
182
 
 
183
BN_ULONG bn_add_words (BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int n)
 
184
{ BN_ULONG ret=0,i=0;
 
185
 
 
186
        if (n <= 0) return 0;
 
187
 
 
188
        asm (
 
189
        "       subq    %2,%2           \n"
 
190
        ".align 16                      \n"
 
191
        "1:     movq    (%4,%2,8),%0    \n"
 
192
        "       adcq    (%5,%2,8),%0    \n"
 
193
        "       movq    %0,(%3,%2,8)    \n"
 
194
        "       leaq    1(%2),%2        \n"
 
195
        "       loop    1b              \n"
 
196
        "       sbbq    %0,%0           \n"
 
197
                : "=&a"(ret),"+c"(n),"=&r"(i)
 
198
                : "r"(rp),"r"(ap),"r"(bp)
 
199
                : "cc"
 
200
        );
 
201
 
 
202
  return ret&1;
 
203
}
 
204
 
 
205
#ifndef SIMICS
 
206
BN_ULONG bn_sub_words (BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int n)
 
207
{ BN_ULONG ret=0,i=0;
 
208
 
 
209
        if (n <= 0) return 0;
 
210
 
 
211
        asm (
 
212
        "       subq    %2,%2           \n"
 
213
        ".align 16                      \n"
 
214
        "1:     movq    (%4,%2,8),%0    \n"
 
215
        "       sbbq    (%5,%2,8),%0    \n"
 
216
        "       movq    %0,(%3,%2,8)    \n"
 
217
        "       leaq    1(%2),%2        \n"
 
218
        "       loop    1b              \n"
 
219
        "       sbbq    %0,%0           \n"
 
220
                : "=&a"(ret),"+c"(n),"=&r"(i)
 
221
                : "r"(rp),"r"(ap),"r"(bp)
 
222
                : "cc"
 
223
        );
 
224
 
 
225
  return ret&1;
 
226
}
 
227
#else
 
228
/* Simics 1.4<7 has buggy sbbq:-( */
 
229
#define BN_MASK2 0xffffffffffffffffL
 
230
BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
 
231
        {
 
232
        BN_ULONG t1,t2;
 
233
        int c=0;
 
234
 
 
235
        if (n <= 0) return((BN_ULONG)0);
 
236
 
 
237
        for (;;)
 
238
                {
 
239
                t1=a[0]; t2=b[0];
 
240
                r[0]=(t1-t2-c)&BN_MASK2;
 
241
                if (t1 != t2) c=(t1 < t2);
 
242
                if (--n <= 0) break;
 
243
 
 
244
                t1=a[1]; t2=b[1];
 
245
                r[1]=(t1-t2-c)&BN_MASK2;
 
246
                if (t1 != t2) c=(t1 < t2);
 
247
                if (--n <= 0) break;
 
248
 
 
249
                t1=a[2]; t2=b[2];
 
250
                r[2]=(t1-t2-c)&BN_MASK2;
 
251
                if (t1 != t2) c=(t1 < t2);
 
252
                if (--n <= 0) break;
 
253
 
 
254
                t1=a[3]; t2=b[3];
 
255
                r[3]=(t1-t2-c)&BN_MASK2;
 
256
                if (t1 != t2) c=(t1 < t2);
 
257
                if (--n <= 0) break;
 
258
 
 
259
                a+=4;
 
260
                b+=4;
 
261
                r+=4;
 
262
                }
 
263
        return(c);
 
264
        }
 
265
#endif
 
266
 
 
267
/* mul_add_c(a,b,c0,c1,c2)  -- c+=a*b for three word number c=(c2,c1,c0) */
 
268
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
 
269
/* sqr_add_c(a,i,c0,c1,c2)  -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
 
270
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */
 
271
 
 
272
#if 0
 
273
/* original macros are kept for reference purposes */
 
274
#define mul_add_c(a,b,c0,c1,c2) {       \
 
275
        BN_ULONG ta=(a),tb=(b);         \
 
276
        t1 = ta * tb;                   \
 
277
        t2 = BN_UMULT_HIGH(ta,tb);      \
 
278
        c0 += t1; t2 += (c0<t1)?1:0;    \
 
279
        c1 += t2; c2 += (c1<t2)?1:0;    \
 
280
        }
 
281
 
 
282
#define mul_add_c2(a,b,c0,c1,c2) {      \
 
283
        BN_ULONG ta=(a),tb=(b),t0;      \
 
284
        t1 = BN_UMULT_HIGH(ta,tb);      \
 
285
        t0 = ta * tb;                   \
 
286
        t2 = t1+t1; c2 += (t2<t1)?1:0;  \
 
287
        t1 = t0+t0; t2 += (t1<t0)?1:0;  \
 
288
        c0 += t1; t2 += (c0<t1)?1:0;    \
 
289
        c1 += t2; c2 += (c1<t2)?1:0;    \
 
290
        }
 
291
#else
 
292
#define mul_add_c(a,b,c0,c1,c2) do {    \
 
293
        asm ("mulq %3"                  \
 
294
                : "=a"(t1),"=d"(t2)     \
 
295
                : "a"(a),"m"(b)         \
 
296
                : "cc");                \
 
297
        asm ("addq %2,%0; adcq %3,%1"   \
 
298
                : "+r"(c0),"+d"(t2)     \
 
299
                : "a"(t1),"g"(0)        \
 
300
                : "cc");                \
 
301
        asm ("addq %2,%0; adcq %3,%1"   \
 
302
                : "+r"(c1),"+r"(c2)     \
 
303
                : "d"(t2),"g"(0)        \
 
304
                : "cc");                \
 
305
        } while (0)
 
306
 
 
307
#define sqr_add_c(a,i,c0,c1,c2) do {    \
 
308
        asm ("mulq %2"                  \
 
309
                : "=a"(t1),"=d"(t2)     \
 
310
                : "a"(a[i])             \
 
311
                : "cc");                \
 
312
        asm ("addq %2,%0; adcq %3,%1"   \
 
313
                : "+r"(c0),"+d"(t2)     \
 
314
                : "a"(t1),"g"(0)        \
 
315
                : "cc");                \
 
316
        asm ("addq %2,%0; adcq %3,%1"   \
 
317
                : "+r"(c1),"+r"(c2)     \
 
318
                : "d"(t2),"g"(0)        \
 
319
                : "cc");                \
 
320
        } while (0)
 
321
 
 
322
#define mul_add_c2(a,b,c0,c1,c2) do {   \
 
323
        asm ("mulq %3"                  \
 
324
                : "=a"(t1),"=d"(t2)     \
 
325
                : "a"(a),"m"(b)         \
 
326
                : "cc");                \
 
327
        asm ("addq %0,%0; adcq %2,%1"   \
 
328
                : "+d"(t2),"+r"(c2)     \
 
329
                : "g"(0)                \
 
330
                : "cc");                \
 
331
        asm ("addq %0,%0; adcq %2,%1"   \
 
332
                : "+a"(t1),"+d"(t2)     \
 
333
                : "g"(0)                \
 
334
                : "cc");                \
 
335
        asm ("addq %2,%0; adcq %3,%1"   \
 
336
                : "+r"(c0),"+d"(t2)     \
 
337
                : "a"(t1),"g"(0)        \
 
338
                : "cc");                \
 
339
        asm ("addq %2,%0; adcq %3,%1"   \
 
340
                : "+r"(c1),"+r"(c2)     \
 
341
                : "d"(t2),"g"(0)        \
 
342
                : "cc");                \
 
343
        } while (0)
 
344
#endif
 
345
 
 
346
#define sqr_add_c2(a,i,j,c0,c1,c2)      \
 
347
        mul_add_c2((a)[i],(a)[j],c0,c1,c2)
 
348
 
 
349
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
 
350
        {
 
351
        BN_ULONG t1,t2;
 
352
        BN_ULONG c1,c2,c3;
 
353
 
 
354
        c1=0;
 
355
        c2=0;
 
356
        c3=0;
 
357
        mul_add_c(a[0],b[0],c1,c2,c3);
 
358
        r[0]=c1;
 
359
        c1=0;
 
360
        mul_add_c(a[0],b[1],c2,c3,c1);
 
361
        mul_add_c(a[1],b[0],c2,c3,c1);
 
362
        r[1]=c2;
 
363
        c2=0;
 
364
        mul_add_c(a[2],b[0],c3,c1,c2);
 
365
        mul_add_c(a[1],b[1],c3,c1,c2);
 
366
        mul_add_c(a[0],b[2],c3,c1,c2);
 
367
        r[2]=c3;
 
368
        c3=0;
 
369
        mul_add_c(a[0],b[3],c1,c2,c3);
 
370
        mul_add_c(a[1],b[2],c1,c2,c3);
 
371
        mul_add_c(a[2],b[1],c1,c2,c3);
 
372
        mul_add_c(a[3],b[0],c1,c2,c3);
 
373
        r[3]=c1;
 
374
        c1=0;
 
375
        mul_add_c(a[4],b[0],c2,c3,c1);
 
376
        mul_add_c(a[3],b[1],c2,c3,c1);
 
377
        mul_add_c(a[2],b[2],c2,c3,c1);
 
378
        mul_add_c(a[1],b[3],c2,c3,c1);
 
379
        mul_add_c(a[0],b[4],c2,c3,c1);
 
380
        r[4]=c2;
 
381
        c2=0;
 
382
        mul_add_c(a[0],b[5],c3,c1,c2);
 
383
        mul_add_c(a[1],b[4],c3,c1,c2);
 
384
        mul_add_c(a[2],b[3],c3,c1,c2);
 
385
        mul_add_c(a[3],b[2],c3,c1,c2);
 
386
        mul_add_c(a[4],b[1],c3,c1,c2);
 
387
        mul_add_c(a[5],b[0],c3,c1,c2);
 
388
        r[5]=c3;
 
389
        c3=0;
 
390
        mul_add_c(a[6],b[0],c1,c2,c3);
 
391
        mul_add_c(a[5],b[1],c1,c2,c3);
 
392
        mul_add_c(a[4],b[2],c1,c2,c3);
 
393
        mul_add_c(a[3],b[3],c1,c2,c3);
 
394
        mul_add_c(a[2],b[4],c1,c2,c3);
 
395
        mul_add_c(a[1],b[5],c1,c2,c3);
 
396
        mul_add_c(a[0],b[6],c1,c2,c3);
 
397
        r[6]=c1;
 
398
        c1=0;
 
399
        mul_add_c(a[0],b[7],c2,c3,c1);
 
400
        mul_add_c(a[1],b[6],c2,c3,c1);
 
401
        mul_add_c(a[2],b[5],c2,c3,c1);
 
402
        mul_add_c(a[3],b[4],c2,c3,c1);
 
403
        mul_add_c(a[4],b[3],c2,c3,c1);
 
404
        mul_add_c(a[5],b[2],c2,c3,c1);
 
405
        mul_add_c(a[6],b[1],c2,c3,c1);
 
406
        mul_add_c(a[7],b[0],c2,c3,c1);
 
407
        r[7]=c2;
 
408
        c2=0;
 
409
        mul_add_c(a[7],b[1],c3,c1,c2);
 
410
        mul_add_c(a[6],b[2],c3,c1,c2);
 
411
        mul_add_c(a[5],b[3],c3,c1,c2);
 
412
        mul_add_c(a[4],b[4],c3,c1,c2);
 
413
        mul_add_c(a[3],b[5],c3,c1,c2);
 
414
        mul_add_c(a[2],b[6],c3,c1,c2);
 
415
        mul_add_c(a[1],b[7],c3,c1,c2);
 
416
        r[8]=c3;
 
417
        c3=0;
 
418
        mul_add_c(a[2],b[7],c1,c2,c3);
 
419
        mul_add_c(a[3],b[6],c1,c2,c3);
 
420
        mul_add_c(a[4],b[5],c1,c2,c3);
 
421
        mul_add_c(a[5],b[4],c1,c2,c3);
 
422
        mul_add_c(a[6],b[3],c1,c2,c3);
 
423
        mul_add_c(a[7],b[2],c1,c2,c3);
 
424
        r[9]=c1;
 
425
        c1=0;
 
426
        mul_add_c(a[7],b[3],c2,c3,c1);
 
427
        mul_add_c(a[6],b[4],c2,c3,c1);
 
428
        mul_add_c(a[5],b[5],c2,c3,c1);
 
429
        mul_add_c(a[4],b[6],c2,c3,c1);
 
430
        mul_add_c(a[3],b[7],c2,c3,c1);
 
431
        r[10]=c2;
 
432
        c2=0;
 
433
        mul_add_c(a[4],b[7],c3,c1,c2);
 
434
        mul_add_c(a[5],b[6],c3,c1,c2);
 
435
        mul_add_c(a[6],b[5],c3,c1,c2);
 
436
        mul_add_c(a[7],b[4],c3,c1,c2);
 
437
        r[11]=c3;
 
438
        c3=0;
 
439
        mul_add_c(a[7],b[5],c1,c2,c3);
 
440
        mul_add_c(a[6],b[6],c1,c2,c3);
 
441
        mul_add_c(a[5],b[7],c1,c2,c3);
 
442
        r[12]=c1;
 
443
        c1=0;
 
444
        mul_add_c(a[6],b[7],c2,c3,c1);
 
445
        mul_add_c(a[7],b[6],c2,c3,c1);
 
446
        r[13]=c2;
 
447
        c2=0;
 
448
        mul_add_c(a[7],b[7],c3,c1,c2);
 
449
        r[14]=c3;
 
450
        r[15]=c1;
 
451
        }
 
452
 
 
453
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
 
454
        {
 
455
        BN_ULONG t1,t2;
 
456
        BN_ULONG c1,c2,c3;
 
457
 
 
458
        c1=0;
 
459
        c2=0;
 
460
        c3=0;
 
461
        mul_add_c(a[0],b[0],c1,c2,c3);
 
462
        r[0]=c1;
 
463
        c1=0;
 
464
        mul_add_c(a[0],b[1],c2,c3,c1);
 
465
        mul_add_c(a[1],b[0],c2,c3,c1);
 
466
        r[1]=c2;
 
467
        c2=0;
 
468
        mul_add_c(a[2],b[0],c3,c1,c2);
 
469
        mul_add_c(a[1],b[1],c3,c1,c2);
 
470
        mul_add_c(a[0],b[2],c3,c1,c2);
 
471
        r[2]=c3;
 
472
        c3=0;
 
473
        mul_add_c(a[0],b[3],c1,c2,c3);
 
474
        mul_add_c(a[1],b[2],c1,c2,c3);
 
475
        mul_add_c(a[2],b[1],c1,c2,c3);
 
476
        mul_add_c(a[3],b[0],c1,c2,c3);
 
477
        r[3]=c1;
 
478
        c1=0;
 
479
        mul_add_c(a[3],b[1],c2,c3,c1);
 
480
        mul_add_c(a[2],b[2],c2,c3,c1);
 
481
        mul_add_c(a[1],b[3],c2,c3,c1);
 
482
        r[4]=c2;
 
483
        c2=0;
 
484
        mul_add_c(a[2],b[3],c3,c1,c2);
 
485
        mul_add_c(a[3],b[2],c3,c1,c2);
 
486
        r[5]=c3;
 
487
        c3=0;
 
488
        mul_add_c(a[3],b[3],c1,c2,c3);
 
489
        r[6]=c1;
 
490
        r[7]=c2;
 
491
        }
 
492
 
 
493
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
 
494
        {
 
495
        BN_ULONG t1,t2;
 
496
        BN_ULONG c1,c2,c3;
 
497
 
 
498
        c1=0;
 
499
        c2=0;
 
500
        c3=0;
 
501
        sqr_add_c(a,0,c1,c2,c3);
 
502
        r[0]=c1;
 
503
        c1=0;
 
504
        sqr_add_c2(a,1,0,c2,c3,c1);
 
505
        r[1]=c2;
 
506
        c2=0;
 
507
        sqr_add_c(a,1,c3,c1,c2);
 
508
        sqr_add_c2(a,2,0,c3,c1,c2);
 
509
        r[2]=c3;
 
510
        c3=0;
 
511
        sqr_add_c2(a,3,0,c1,c2,c3);
 
512
        sqr_add_c2(a,2,1,c1,c2,c3);
 
513
        r[3]=c1;
 
514
        c1=0;
 
515
        sqr_add_c(a,2,c2,c3,c1);
 
516
        sqr_add_c2(a,3,1,c2,c3,c1);
 
517
        sqr_add_c2(a,4,0,c2,c3,c1);
 
518
        r[4]=c2;
 
519
        c2=0;
 
520
        sqr_add_c2(a,5,0,c3,c1,c2);
 
521
        sqr_add_c2(a,4,1,c3,c1,c2);
 
522
        sqr_add_c2(a,3,2,c3,c1,c2);
 
523
        r[5]=c3;
 
524
        c3=0;
 
525
        sqr_add_c(a,3,c1,c2,c3);
 
526
        sqr_add_c2(a,4,2,c1,c2,c3);
 
527
        sqr_add_c2(a,5,1,c1,c2,c3);
 
528
        sqr_add_c2(a,6,0,c1,c2,c3);
 
529
        r[6]=c1;
 
530
        c1=0;
 
531
        sqr_add_c2(a,7,0,c2,c3,c1);
 
532
        sqr_add_c2(a,6,1,c2,c3,c1);
 
533
        sqr_add_c2(a,5,2,c2,c3,c1);
 
534
        sqr_add_c2(a,4,3,c2,c3,c1);
 
535
        r[7]=c2;
 
536
        c2=0;
 
537
        sqr_add_c(a,4,c3,c1,c2);
 
538
        sqr_add_c2(a,5,3,c3,c1,c2);
 
539
        sqr_add_c2(a,6,2,c3,c1,c2);
 
540
        sqr_add_c2(a,7,1,c3,c1,c2);
 
541
        r[8]=c3;
 
542
        c3=0;
 
543
        sqr_add_c2(a,7,2,c1,c2,c3);
 
544
        sqr_add_c2(a,6,3,c1,c2,c3);
 
545
        sqr_add_c2(a,5,4,c1,c2,c3);
 
546
        r[9]=c1;
 
547
        c1=0;
 
548
        sqr_add_c(a,5,c2,c3,c1);
 
549
        sqr_add_c2(a,6,4,c2,c3,c1);
 
550
        sqr_add_c2(a,7,3,c2,c3,c1);
 
551
        r[10]=c2;
 
552
        c2=0;
 
553
        sqr_add_c2(a,7,4,c3,c1,c2);
 
554
        sqr_add_c2(a,6,5,c3,c1,c2);
 
555
        r[11]=c3;
 
556
        c3=0;
 
557
        sqr_add_c(a,6,c1,c2,c3);
 
558
        sqr_add_c2(a,7,5,c1,c2,c3);
 
559
        r[12]=c1;
 
560
        c1=0;
 
561
        sqr_add_c2(a,7,6,c2,c3,c1);
 
562
        r[13]=c2;
 
563
        c2=0;
 
564
        sqr_add_c(a,7,c3,c1,c2);
 
565
        r[14]=c3;
 
566
        r[15]=c1;
 
567
        }
 
568
 
 
569
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
 
570
        {
 
571
        BN_ULONG t1,t2;
 
572
        BN_ULONG c1,c2,c3;
 
573
 
 
574
        c1=0;
 
575
        c2=0;
 
576
        c3=0;
 
577
        sqr_add_c(a,0,c1,c2,c3);
 
578
        r[0]=c1;
 
579
        c1=0;
 
580
        sqr_add_c2(a,1,0,c2,c3,c1);
 
581
        r[1]=c2;
 
582
        c2=0;
 
583
        sqr_add_c(a,1,c3,c1,c2);
 
584
        sqr_add_c2(a,2,0,c3,c1,c2);
 
585
        r[2]=c3;
 
586
        c3=0;
 
587
        sqr_add_c2(a,3,0,c1,c2,c3);
 
588
        sqr_add_c2(a,2,1,c1,c2,c3);
 
589
        r[3]=c1;
 
590
        c1=0;
 
591
        sqr_add_c(a,2,c2,c3,c1);
 
592
        sqr_add_c2(a,3,1,c2,c3,c1);
 
593
        r[4]=c2;
 
594
        c2=0;
 
595
        sqr_add_c2(a,3,2,c3,c1,c2);
 
596
        r[5]=c3;
 
597
        c3=0;
 
598
        sqr_add_c(a,3,c1,c2,c3);
 
599
        r[6]=c1;
 
600
        r[7]=c2;
 
601
        }
 
602
#endif