1 /*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6 #include "tls.h"
7
8 /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12 /**
13 * @file pstm_mul_comba.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision multiplication with Comba technique.
17 */
18 /*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44 /******************************************************************************/
45
46 //bbox
47 //#include "../cryptoApi.h"
48 #ifndef DISABLE_PSTM
49
50 /******************************************************************************/
51 #if defined(PSTM_X86)
52 /* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
53 #if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT)
54 #error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
55 #endif
56 //#pragma message ("Using 32 bit x86 Assembly Optimizations")
57
58 /* anything you need at the start */
59 #define COMBA_START
60
61 /* clear the chaining variables */
62 #define COMBA_CLEAR \
63 c0 = c1 = c2 = 0;
64
65 /* forward the carry to the next digit */
66 #define COMBA_FORWARD \
67 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
68
69 /* store the first sum */
70 #define COMBA_STORE(x) \
71 x = c0;
72
73 /* store the second sum [carry] */
74 #define COMBA_STORE2(x) \
75 x = c1;
76
77 /* anything you need at the end */
78 #define COMBA_FINI
79
80 /* this should multiply i and j */
81 #define MULADD(i, j) \
82 asm( \
83 "movl %6,%%eax \n\t" \
84 "mull %7 \n\t" \
85 "addl %%eax,%0 \n\t" \
86 "adcl %%edx,%1 \n\t" \
87 "adcl $0,%2 \n\t" \
88 :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc");
89 //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build
90
91 /******************************************************************************/
92 #elif defined(PSTM_X86_64)
93 /* x86-64 optimized */
94 #if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
95 #error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
96 #endif
97 //#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
98
99 /* anything you need at the start */
100 #define COMBA_START
101
102 /* clear the chaining variables */
103 #define COMBA_CLEAR \
104 c0 = c1 = c2 = 0;
105
106 /* forward the carry to the next digit */
107 #define COMBA_FORWARD \
108 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
109
110 /* store the first sum */
111 #define COMBA_STORE(x) \
112 x = c0;
113
114 /* store the second sum [carry] */
115 #define COMBA_STORE2(x) \
116 x = c1;
117
118 /* anything you need at the end */
119 #define COMBA_FINI
120
121 /* this should multiply i and j */
122 #define MULADD(i, j) \
123 asm ( \
124 "movq %6,%%rax \n\t" \
125 "mulq %7 \n\t" \
126 "addq %%rax,%0 \n\t" \
127 "adcq %%rdx,%1 \n\t" \
128 "adcq $0,%2 \n\t" \
129 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc");
130
131 /******************************************************************************/
132 #elif defined(PSTM_ARM)
133 /* ARM code */
134 //#pragma message ("Using 32 bit ARM Assembly Optimizations")
135
136 #define COMBA_START
137
138 #define COMBA_CLEAR \
139 c0 = c1 = c2 = 0;
140
141 #define COMBA_FORWARD \
142 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
143
144 #define COMBA_STORE(x) \
145 x = c0;
146
147 #define COMBA_STORE2(x) \
148 x = c1;
149
150 #define COMBA_FINI
151
152 #define MULADD(i, j) \
153 asm( \
154 " UMULL r0,r1,%6,%7 \n\t" \
155 " ADDS %0,%0,r0 \n\t" \
156 " ADCS %1,%1,r1 \n\t" \
157 " ADC %2,%2,#0 \n\t" \
158 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc");
159
160 /******************************************************************************/
161 #elif defined(PSTM_MIPS)
162 /* MIPS32 code */
163 //#pragma message ("Using 32 bit MIPS Assembly Optimizations")
164
165 #define COMBA_START
166
167 #define COMBA_CLEAR \
168 c0 = c1 = c2 = 0;
169
170 #define COMBA_FORWARD \
171 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
172
173 #define COMBA_STORE(x) \
174 x = c0;
175
176 #define COMBA_STORE2(x) \
177 x = c1;
178
179 #define COMBA_FINI
180
181 #define MULADD(i, j) \
182 asm( \
183 " multu %6,%7 \n\t" \
184 " mflo $12 \n\t" \
185 " mfhi $13 \n\t" \
186 " addu %0,%0,$12 \n\t" \
187 " sltu $12,%0,$12 \n\t" \
188 " addu %1,%1,$13 \n\t" \
189 " sltu $13,%1,$13 \n\t" \
190 " addu %1,%1,$12 \n\t" \
191 " sltu $12,%1,$12 \n\t" \
192 " addu %2,%2,$13 \n\t" \
193 " addu %2,%2,$12 \n\t" \
194 :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13");
195
196 /******************************************************************************/
197 #else
198
199 #define COMBA_START
200
201 #define COMBA_CLEAR \
202 c0 = c1 = c2 = 0;
203
204 #define COMBA_FORWARD \
205 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
206
207 #define COMBA_STORE(x) \
208 x = c0;
209
210 #define COMBA_STORE2(x) \
211 x = c1;
212
213 #define COMBA_FINI
214
215 #define MULADD(i, j) \
216 do { pstm_word t; \
217 t = (pstm_word)c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \
218 t = (pstm_word)c1 + (t >> DIGIT_BIT); \
219 c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \
220 } while (0);
221
222 #endif
223
224 /******************************************************************************/
225 /* generic PxQ multiplier */
226 //bbox: pool unused
227 #define pstm_mul_comba_gen(pool, A, B, C, paD, paDlen) \
228 pstm_mul_comba_gen( A, B, C, paD, paDlen)
pstm_mul_comba_gen(psPool_t * pool,pstm_int * A,pstm_int * B,pstm_int * C,pstm_digit * paD,uint32 paDlen)229 static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
230 pstm_int *C, pstm_digit *paD, uint32 paDlen)
231 {
232 int paDfail, pa; //bbox: was int16
233 int32 ix, iy, iz, tx, ty;
234 pstm_digit c0, c1, c2, *tmpx, *tmpy, *dst;
235
236 COMBA_START;
237 COMBA_CLEAR;
238
239 paDfail = 0;
240 /* get size of output and trim */
241 pa = A->used + B->used;
242
243 /*
244 If c is not large enough grow it and continue
245 */
246 if (C->alloc < pa) {
247 if (pstm_grow(C, pa) != PSTM_OKAY) {
248 return PS_MEM_FAIL;
249 }
250 }
251 if (paD != NULL) {
252 if (paDlen < (sizeof(pstm_digit) * pa)) {
253 paDfail = 1; /* have a paD but it's not large enough */
254 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
255 } else {
256 dst = paD;
257 memset(dst, 0x0, paDlen);
258 }
259 } else {
260 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
261 }
262
263 for (ix = 0; ix < pa; ix++) {
264 /* get offsets into the two bignums */
265 ty = min(ix, B->used-1);
266 tx = ix - ty;
267
268 /* setup temp aliases */
269 tmpx = A->dp + tx;
270 tmpy = B->dp + ty;
271 /*
272 This is the number of times the loop will iterate, essentially it's
273 while (tx++ < a->used && ty-- >= 0) { ... }
274 */
275 iy = min(A->used-tx, ty+1);
276
277 /* execute loop */
278 COMBA_FORWARD;
279 for (iz = 0; iz < iy; ++iz) {
280 MULADD(*tmpx++, *tmpy--);
281 }
282
283 /* store term */
284 COMBA_STORE(dst[ix]);
285 }
286 COMBA_FINI;
287 /*
288 setup dest
289 */
290 iy = C->used;
291 C->used = pa;
292 C->sign = A->sign ^ B->sign;
293 {
294 pstm_digit *tmpc;
295 tmpc = C->dp;
296 for (ix = 0; ix < pa; ix++) {
297 *tmpc++ = dst[ix];
298 }
299 /*
300 clear unused digits [that existed in the old copy of c]
301 */
302 for (; ix < iy; ix++) {
303 *tmpc++ = 0;
304 }
305 }
306 pstm_clamp(C);
307
308 if ((paD == NULL) || (paDfail == 1)) {
309 psFree(dst, pool);
310 }
311
312 return PS_SUCCESS;
313 }
314
315 /******************************************************************************/
316 #ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
pstm_mul_comba16(pstm_int * A,pstm_int * B,pstm_int * C)317 static int32 pstm_mul_comba16(pstm_int *A, pstm_int *B, pstm_int *C)
318 {
319 pstm_digit c0, c1, c2, at[32];
320
321 if (C->alloc < 32) {
322 if (pstm_grow(C, 32) != PSTM_OKAY) {
323 return PS_MEM_FAIL;
324 }
325 }
326 memcpy(at, A->dp, 16 * sizeof(pstm_digit));
327 memcpy(at+16, B->dp, 16 * sizeof(pstm_digit));
328
329 COMBA_START;
330
331 COMBA_CLEAR;
332 /* 0 */
333 MULADD(at[0], at[16]);
334 COMBA_STORE(C->dp[0]);
335 /* 1 */
336 COMBA_FORWARD;
337 MULADD(at[0], at[17]); MULADD(at[1], at[16]);
338 COMBA_STORE(C->dp[1]);
339 /* 2 */
340 COMBA_FORWARD;
341 MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]);
342 COMBA_STORE(C->dp[2]);
343 /* 3 */
344 COMBA_FORWARD;
345 MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]);
346 COMBA_STORE(C->dp[3]);
347 /* 4 */
348 COMBA_FORWARD;
349 MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]);
350 COMBA_STORE(C->dp[4]);
351 /* 5 */
352 COMBA_FORWARD;
353 MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]);
354 COMBA_STORE(C->dp[5]);
355 /* 6 */
356 COMBA_FORWARD;
357 MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]);
358 COMBA_STORE(C->dp[6]);
359 /* 7 */
360 COMBA_FORWARD;
361 MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]);
362 COMBA_STORE(C->dp[7]);
363 /* 8 */
364 COMBA_FORWARD;
365 MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]);
366 COMBA_STORE(C->dp[8]);
367 /* 9 */
368 COMBA_FORWARD;
369 MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]);
370 COMBA_STORE(C->dp[9]);
371 /* 10 */
372 COMBA_FORWARD;
373 MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]);
374 COMBA_STORE(C->dp[10]);
375 /* 11 */
376 COMBA_FORWARD;
377 MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]);
378 COMBA_STORE(C->dp[11]);
379 /* 12 */
380 COMBA_FORWARD;
381 MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]);
382 COMBA_STORE(C->dp[12]);
383 /* 13 */
384 COMBA_FORWARD;
385 MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]);
386 COMBA_STORE(C->dp[13]);
387 /* 14 */
388 COMBA_FORWARD;
389 MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); MULADD(at[14], at[16]);
390 COMBA_STORE(C->dp[14]);
391 /* 15 */
392 COMBA_FORWARD;
393 MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); MULADD(at[15], at[16]);
394 COMBA_STORE(C->dp[15]);
395 /* 16 */
396 COMBA_FORWARD;
397 MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); MULADD(at[15], at[17]);
398 COMBA_STORE(C->dp[16]);
399 /* 17 */
400 COMBA_FORWARD;
401 MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); MULADD(at[15], at[18]);
402 COMBA_STORE(C->dp[17]);
403 /* 18 */
404 COMBA_FORWARD;
405 MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); MULADD(at[15], at[19]);
406 COMBA_STORE(C->dp[18]);
407 /* 19 */
408 COMBA_FORWARD;
409 MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]);
410 COMBA_STORE(C->dp[19]);
411 /* 20 */
412 COMBA_FORWARD;
413 MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]);
414 COMBA_STORE(C->dp[20]);
415 /* 21 */
416 COMBA_FORWARD;
417 MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]);
418 COMBA_STORE(C->dp[21]);
419 /* 22 */
420 COMBA_FORWARD;
421 MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]);
422 COMBA_STORE(C->dp[22]);
423 /* 23 */
424 COMBA_FORWARD;
425 MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]);
426 COMBA_STORE(C->dp[23]);
427 /* 24 */
428 COMBA_FORWARD;
429 MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]);
430 COMBA_STORE(C->dp[24]);
431 /* 25 */
432 COMBA_FORWARD;
433 MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]);
434 COMBA_STORE(C->dp[25]);
435 /* 26 */
436 COMBA_FORWARD;
437 MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]);
438 COMBA_STORE(C->dp[26]);
439 /* 27 */
440 COMBA_FORWARD;
441 MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]);
442 COMBA_STORE(C->dp[27]);
443 /* 28 */
444 COMBA_FORWARD;
445 MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]);
446 COMBA_STORE(C->dp[28]);
447 /* 29 */
448 COMBA_FORWARD;
449 MULADD(at[14], at[31]); MULADD(at[15], at[30]);
450 COMBA_STORE(C->dp[29]);
451 /* 30 */
452 COMBA_FORWARD;
453 MULADD(at[15], at[31]);
454 COMBA_STORE(C->dp[30]);
455 COMBA_STORE2(C->dp[31]);
456 C->used = 32;
457 C->sign = A->sign ^ B->sign;
458 pstm_clamp(C);
459 COMBA_FINI;
460 return PSTM_OKAY;
461 }
462 #endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */
463
464
465 #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
pstm_mul_comba32(pstm_int * A,pstm_int * B,pstm_int * C)466 static int32 pstm_mul_comba32(pstm_int *A, pstm_int *B, pstm_int *C)
467 {
468 pstm_digit c0, c1, c2, at[64];
469 int32 out_size;
470
471 if (C->alloc < 64) {
472 if (pstm_grow(C, 64) != PSTM_OKAY) {
473 return PS_MEM_FAIL;
474 }
475 }
476
477 out_size = A->used + B->used;
478 memcpy(at, A->dp, 32 * sizeof(pstm_digit));
479 memcpy(at+32, B->dp, 32 * sizeof(pstm_digit));
480 COMBA_START;
481
482 COMBA_CLEAR;
483 /* 0 */
484 MULADD(at[0], at[32]);
485 COMBA_STORE(C->dp[0]);
486 /* 1 */
487 COMBA_FORWARD;
488 MULADD(at[0], at[33]); MULADD(at[1], at[32]);
489 COMBA_STORE(C->dp[1]);
490 /* 2 */
491 COMBA_FORWARD;
492 MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]);
493 COMBA_STORE(C->dp[2]);
494 /* 3 */
495 COMBA_FORWARD;
496 MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]);
497 COMBA_STORE(C->dp[3]);
498 /* 4 */
499 COMBA_FORWARD;
500 MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]);
501 COMBA_STORE(C->dp[4]);
502 /* 5 */
503 COMBA_FORWARD;
504 MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]);
505 COMBA_STORE(C->dp[5]);
506 /* 6 */
507 COMBA_FORWARD;
508 MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]);
509 COMBA_STORE(C->dp[6]);
510 /* 7 */
511 COMBA_FORWARD;
512 MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]);
513 COMBA_STORE(C->dp[7]);
514 /* 8 */
515 COMBA_FORWARD;
516 MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]);
517 COMBA_STORE(C->dp[8]);
518 /* 9 */
519 COMBA_FORWARD;
520 MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]);
521 COMBA_STORE(C->dp[9]);
522 /* 10 */
523 COMBA_FORWARD;
524 MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]);
525 COMBA_STORE(C->dp[10]);
526 /* 11 */
527 COMBA_FORWARD;
528 MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]);
529 COMBA_STORE(C->dp[11]);
530 /* 12 */
531 COMBA_FORWARD;
532 MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]);
533 COMBA_STORE(C->dp[12]);
534 /* 13 */
535 COMBA_FORWARD;
536 MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]);
537 COMBA_STORE(C->dp[13]);
538 /* 14 */
539 COMBA_FORWARD;
540 MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]);
541 COMBA_STORE(C->dp[14]);
542 /* 15 */
543 COMBA_FORWARD;
544 MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]);
545 COMBA_STORE(C->dp[15]);
546 /* 16 */
547 COMBA_FORWARD;
548 MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]);
549 COMBA_STORE(C->dp[16]);
550 /* 17 */
551 COMBA_FORWARD;
552 MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]);
553 COMBA_STORE(C->dp[17]);
554 /* 18 */
555 COMBA_FORWARD;
556 MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]);
557 COMBA_STORE(C->dp[18]);
558 /* 19 */
559 COMBA_FORWARD;
560 MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]);
561 COMBA_STORE(C->dp[19]);
562 /* 20 */
563 COMBA_FORWARD;
564 MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]);
565 COMBA_STORE(C->dp[20]);
566 /* 21 */
567 COMBA_FORWARD;
568 MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]);
569 COMBA_STORE(C->dp[21]);
570 /* 22 */
571 COMBA_FORWARD;
572 MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]);
573 COMBA_STORE(C->dp[22]);
574 /* 23 */
575 COMBA_FORWARD;
576 MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]);
577 COMBA_STORE(C->dp[23]);
578 /* 24 */
579 COMBA_FORWARD;
580 MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]);
581 COMBA_STORE(C->dp[24]);
582 /* 25 */
583 COMBA_FORWARD;
584 MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]);
585 COMBA_STORE(C->dp[25]);
586 /* 26 */
587 COMBA_FORWARD;
588 MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]);
589 COMBA_STORE(C->dp[26]);
590 /* 27 */
591 COMBA_FORWARD;
592 MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]);
593 COMBA_STORE(C->dp[27]);
594 /* 28 */
595 COMBA_FORWARD;
596 MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); MULADD(at[28], at[32]);
597 COMBA_STORE(C->dp[28]);
598 /* 29 */
599 COMBA_FORWARD;
600 MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); MULADD(at[28], at[33]); MULADD(at[29], at[32]);
601 COMBA_STORE(C->dp[29]);
602 /* 30 */
603 COMBA_FORWARD;
604 MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); MULADD(at[28], at[34]); MULADD(at[29], at[33]); MULADD(at[30], at[32]);
605 COMBA_STORE(C->dp[30]);
606 /* 31 */
607 COMBA_FORWARD;
608 MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); MULADD(at[28], at[35]); MULADD(at[29], at[34]); MULADD(at[30], at[33]); MULADD(at[31], at[32]);
609 COMBA_STORE(C->dp[31]);
610 /* 32 */
611 COMBA_FORWARD;
612 MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); MULADD(at[28], at[36]); MULADD(at[29], at[35]); MULADD(at[30], at[34]); MULADD(at[31], at[33]);
613 COMBA_STORE(C->dp[32]);
614 /* 33 */
615 COMBA_FORWARD;
616 MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); MULADD(at[28], at[37]); MULADD(at[29], at[36]); MULADD(at[30], at[35]); MULADD(at[31], at[34]);
617 COMBA_STORE(C->dp[33]);
618 /* 34 */
619 COMBA_FORWARD;
620 MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); MULADD(at[28], at[38]); MULADD(at[29], at[37]); MULADD(at[30], at[36]); MULADD(at[31], at[35]);
621 COMBA_STORE(C->dp[34]);
622 /* 35 */
623 COMBA_FORWARD;
624 MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); MULADD(at[28], at[39]); MULADD(at[29], at[38]); MULADD(at[30], at[37]); MULADD(at[31], at[36]);
625 COMBA_STORE(C->dp[35]);
626 /* 36 */
627 COMBA_FORWARD;
628 MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); MULADD(at[28], at[40]); MULADD(at[29], at[39]); MULADD(at[30], at[38]); MULADD(at[31], at[37]);
629 COMBA_STORE(C->dp[36]);
630 /* 37 */
631 COMBA_FORWARD;
632 MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); MULADD(at[28], at[41]); MULADD(at[29], at[40]); MULADD(at[30], at[39]); MULADD(at[31], at[38]);
633 COMBA_STORE(C->dp[37]);
634 /* 38 */
635 COMBA_FORWARD;
636 MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); MULADD(at[28], at[42]); MULADD(at[29], at[41]); MULADD(at[30], at[40]); MULADD(at[31], at[39]);
637 COMBA_STORE(C->dp[38]);
638
639 /* early out at 40 digits, 40*32==1280, or two 640 bit operands */
640 if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
641
642 /* 39 */
643 COMBA_FORWARD;
644 MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); MULADD(at[28], at[43]); MULADD(at[29], at[42]); MULADD(at[30], at[41]); MULADD(at[31], at[40]);
645 COMBA_STORE(C->dp[39]);
646 /* 40 */
647 COMBA_FORWARD;
648 MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); MULADD(at[28], at[44]); MULADD(at[29], at[43]); MULADD(at[30], at[42]); MULADD(at[31], at[41]);
649 COMBA_STORE(C->dp[40]);
650 /* 41 */
651 COMBA_FORWARD;
652 MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); MULADD(at[28], at[45]); MULADD(at[29], at[44]); MULADD(at[30], at[43]); MULADD(at[31], at[42]);
653 COMBA_STORE(C->dp[41]);
654 /* 42 */
655 COMBA_FORWARD;
656 MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); MULADD(at[28], at[46]); MULADD(at[29], at[45]); MULADD(at[30], at[44]); MULADD(at[31], at[43]);
657 COMBA_STORE(C->dp[42]);
658 /* 43 */
659 COMBA_FORWARD;
660 MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); MULADD(at[28], at[47]); MULADD(at[29], at[46]); MULADD(at[30], at[45]); MULADD(at[31], at[44]);
661 COMBA_STORE(C->dp[43]);
662 /* 44 */
663 COMBA_FORWARD;
664 MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); MULADD(at[29], at[47]); MULADD(at[30], at[46]); MULADD(at[31], at[45]);
665 COMBA_STORE(C->dp[44]);
666 /* 45 */
667 COMBA_FORWARD;
668 MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); MULADD(at[30], at[47]); MULADD(at[31], at[46]);
669 COMBA_STORE(C->dp[45]);
670 /* 46 */
671 COMBA_FORWARD;
672 MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); MULADD(at[31], at[47]);
673 COMBA_STORE(C->dp[46]);
674
675 /* early out at 48 digits, 48*32==1536, or two 768 bit operands */
676 if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
677
678 /* 47 */
679 COMBA_FORWARD;
680 MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]);
681 COMBA_STORE(C->dp[47]);
682 /* 48 */
683 COMBA_FORWARD;
684 MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]);
685 COMBA_STORE(C->dp[48]);
686 /* 49 */
687 COMBA_FORWARD;
688 MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]);
689 COMBA_STORE(C->dp[49]);
690 /* 50 */
691 COMBA_FORWARD;
692 MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]);
693 COMBA_STORE(C->dp[50]);
694 /* 51 */
695 COMBA_FORWARD;
696 MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]);
697 COMBA_STORE(C->dp[51]);
698 /* 52 */
699 COMBA_FORWARD;
700 MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]);
701 COMBA_STORE(C->dp[52]);
702 /* 53 */
703 COMBA_FORWARD;
704 MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]);
705 COMBA_STORE(C->dp[53]);
706 /* 54 */
707 COMBA_FORWARD;
708 MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]);
709 COMBA_STORE(C->dp[54]);
710
711 /* early out at 56 digits, 56*32==1792, or two 896 bit operands */
712 if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
713
714 /* 55 */
715 COMBA_FORWARD;
716 MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]);
717 COMBA_STORE(C->dp[55]);
718 /* 56 */
719 COMBA_FORWARD;
720 MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]);
721 COMBA_STORE(C->dp[56]);
722 /* 57 */
723 COMBA_FORWARD;
724 MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]);
725 COMBA_STORE(C->dp[57]);
726 /* 58 */
727 COMBA_FORWARD;
728 MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]);
729 COMBA_STORE(C->dp[58]);
730 /* 59 */
731 COMBA_FORWARD;
732 MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]);
733 COMBA_STORE(C->dp[59]);
734 /* 60 */
735 COMBA_FORWARD;
736 MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]);
737 COMBA_STORE(C->dp[60]);
738 /* 61 */
739 COMBA_FORWARD;
740 MULADD(at[30], at[63]); MULADD(at[31], at[62]);
741 COMBA_STORE(C->dp[61]);
742 /* 62 */
743 COMBA_FORWARD;
744 MULADD(at[31], at[63]);
745 COMBA_STORE(C->dp[62]);
746 COMBA_STORE2(C->dp[63]);
747 C->used = 64;
748 C->sign = A->sign ^ B->sign;
749 pstm_clamp(C);
750 COMBA_FINI;
751 return PSTM_OKAY;
752 }
753 #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
754
755 /******************************************************************************/
756
pstm_mul_comba(psPool_t * pool,pstm_int * A,pstm_int * B,pstm_int * C,pstm_digit * paD,uint32 paDlen)757 int32 FAST_FUNC pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C,
758 pstm_digit *paD, uint32 paDlen)
759 {
760 #ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
761 if (A->used == 16 && B->used == 16) {
762 return pstm_mul_comba16(A, B, C);
763 } else {
764 #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
765 if (A->used == 32 && B->used == 32) {
766 return pstm_mul_comba32(A, B, C);
767 }
768 #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
769 return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen);
770 }
771 #else
772 #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
773 if (A->used == 32 && B->used == 32) {
774 return pstm_mul_comba32(A, B, C);
775 }
776 #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
777 return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen);
778 #endif
779 }
780
781 #endif /* !DISABLE_PSTM */
782 /******************************************************************************/
783