• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
bn_mul_add_words(BN_ULONG * rp,const BN_ULONG * ap,int num,BN_ULONG w)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 
bn_mul_words(BN_ULONG * rp,const BN_ULONG * ap,int num,BN_ULONG w)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 
bn_sqr_words(BN_ULONG * r,const BN_ULONG * a,int n)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 
bn_div_words(BN_ULONG h,BN_ULONG l,BN_ULONG d)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 
bn_add_words(BN_ULONG * rp,const BN_ULONG * ap,const BN_ULONG * bp,int n)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
bn_sub_words(BN_ULONG * rp,const BN_ULONG * ap,const BN_ULONG * bp,int n)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
bn_sub_words(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n)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 
bn_mul_comba8(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b)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 
bn_mul_comba4(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b)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 
bn_sqr_comba8(BN_ULONG * r,const BN_ULONG * a)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 
bn_sqr_comba4(BN_ULONG * r,const BN_ULONG * a)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
607