PolarSSL v1.1.4
bn_mul.h
Go to the documentation of this file.
1 
27 /*
28  * Multiply source vector [s] with b, add result
29  * to destination vector [d] and set carry c.
30  *
31  * Currently supports:
32  *
33  * . IA-32 (386+) . AMD64 / EM64T
34  * . IA-32 (SSE2) . Motorola 68000
35  * . PowerPC, 32-bit . MicroBlaze
36  * . PowerPC, 64-bit . TriCore
37  * . SPARC v8 . ARM v3+
38  * . Alpha . MIPS32
39  * . C, longlong . C, generic
40  */
41 #ifndef POLARSSL_BN_MUL_H
42 #define POLARSSL_BN_MUL_H
43 
44 #include "bignum.h"
45 
46 #if defined(POLARSSL_HAVE_ASM)
47 
48 #if defined(__GNUC__)
49 #if defined(__i386__)
50 
51 #define MULADDC_INIT \
52  asm( " \
53  movl %%ebx, %0; \
54  movl %5, %%esi; \
55  movl %6, %%edi; \
56  movl %7, %%ecx; \
57  movl %8, %%ebx; \
58  "
59 
60 #define MULADDC_CORE \
61  " \
62  lodsl; \
63  mull %%ebx; \
64  addl %%ecx, %%eax; \
65  adcl $0, %%edx; \
66  addl (%%edi), %%eax; \
67  adcl $0, %%edx; \
68  movl %%edx, %%ecx; \
69  stosl; \
70  "
71 
72 #if defined(POLARSSL_HAVE_SSE2)
73 
74 #define MULADDC_HUIT \
75  " \
76  movd %%ecx, %%mm1; \
77  movd %%ebx, %%mm0; \
78  movd (%%edi), %%mm3; \
79  paddq %%mm3, %%mm1; \
80  movd (%%esi), %%mm2; \
81  pmuludq %%mm0, %%mm2; \
82  movd 4(%%esi), %%mm4; \
83  pmuludq %%mm0, %%mm4; \
84  movd 8(%%esi), %%mm6; \
85  pmuludq %%mm0, %%mm6; \
86  movd 12(%%esi), %%mm7; \
87  pmuludq %%mm0, %%mm7; \
88  paddq %%mm2, %%mm1; \
89  movd 4(%%edi), %%mm3; \
90  paddq %%mm4, %%mm3; \
91  movd 8(%%edi), %%mm5; \
92  paddq %%mm6, %%mm5; \
93  movd 12(%%edi), %%mm4; \
94  paddq %%mm4, %%mm7; \
95  movd %%mm1, (%%edi); \
96  movd 16(%%esi), %%mm2; \
97  pmuludq %%mm0, %%mm2; \
98  psrlq $32, %%mm1; \
99  movd 20(%%esi), %%mm4; \
100  pmuludq %%mm0, %%mm4; \
101  paddq %%mm3, %%mm1; \
102  movd 24(%%esi), %%mm6; \
103  pmuludq %%mm0, %%mm6; \
104  movd %%mm1, 4(%%edi); \
105  psrlq $32, %%mm1; \
106  movd 28(%%esi), %%mm3; \
107  pmuludq %%mm0, %%mm3; \
108  paddq %%mm5, %%mm1; \
109  movd 16(%%edi), %%mm5; \
110  paddq %%mm5, %%mm2; \
111  movd %%mm1, 8(%%edi); \
112  psrlq $32, %%mm1; \
113  paddq %%mm7, %%mm1; \
114  movd 20(%%edi), %%mm5; \
115  paddq %%mm5, %%mm4; \
116  movd %%mm1, 12(%%edi); \
117  psrlq $32, %%mm1; \
118  paddq %%mm2, %%mm1; \
119  movd 24(%%edi), %%mm5; \
120  paddq %%mm5, %%mm6; \
121  movd %%mm1, 16(%%edi); \
122  psrlq $32, %%mm1; \
123  paddq %%mm4, %%mm1; \
124  movd 28(%%edi), %%mm5; \
125  paddq %%mm5, %%mm3; \
126  movd %%mm1, 20(%%edi); \
127  psrlq $32, %%mm1; \
128  paddq %%mm6, %%mm1; \
129  movd %%mm1, 24(%%edi); \
130  psrlq $32, %%mm1; \
131  paddq %%mm3, %%mm1; \
132  movd %%mm1, 28(%%edi); \
133  addl $32, %%edi; \
134  addl $32, %%esi; \
135  psrlq $32, %%mm1; \
136  movd %%mm1, %%ecx; \
137  "
138 
139 #define MULADDC_STOP \
140  " \
141  emms; \
142  movl %4, %%ebx; \
143  movl %%ecx, %1; \
144  movl %%edi, %2; \
145  movl %%esi, %3; \
146  " \
147  : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
148  : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
149  : "eax", "ecx", "edx", "esi", "edi" \
150  );
151 
152 #else
153 
154 #define MULADDC_STOP \
155  " \
156  movl %4, %%ebx; \
157  movl %%ecx, %1; \
158  movl %%edi, %2; \
159  movl %%esi, %3; \
160  " \
161  : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
162  : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
163  : "eax", "ecx", "edx", "esi", "edi" \
164  );
165 #endif /* SSE2 */
166 #endif /* i386 */
167 
168 #if defined(__amd64__) || defined (__x86_64__)
169 
170 #define MULADDC_INIT \
171  asm( "movq %0, %%rsi " :: "m" (s)); \
172  asm( "movq %0, %%rdi " :: "m" (d)); \
173  asm( "movq %0, %%rcx " :: "m" (c)); \
174  asm( "movq %0, %%rbx " :: "m" (b)); \
175  asm( "xorq %r8, %r8 " );
176 
177 #define MULADDC_CORE \
178  asm( "movq (%rsi),%rax " ); \
179  asm( "mulq %rbx " ); \
180  asm( "addq $8, %rsi " ); \
181  asm( "addq %rcx, %rax " ); \
182  asm( "movq %r8, %rcx " ); \
183  asm( "adcq $0, %rdx " ); \
184  asm( "nop " ); \
185  asm( "addq %rax, (%rdi) " ); \
186  asm( "adcq %rdx, %rcx " ); \
187  asm( "addq $8, %rdi " );
188 
189 #define MULADDC_STOP \
190  asm( "movq %%rcx, %0 " : "=m" (c)); \
191  asm( "movq %%rdi, %0 " : "=m" (d)); \
192  asm( "movq %%rsi, %0 " : "=m" (s) :: \
193  "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
194 
195 #endif /* AMD64 */
196 
197 #if defined(__mc68020__) || defined(__mcpu32__)
198 
199 #define MULADDC_INIT \
200  asm( "movl %0, %%a2 " :: "m" (s)); \
201  asm( "movl %0, %%a3 " :: "m" (d)); \
202  asm( "movl %0, %%d3 " :: "m" (c)); \
203  asm( "movl %0, %%d2 " :: "m" (b)); \
204  asm( "moveq #0, %d0 " );
205 
206 #define MULADDC_CORE \
207  asm( "movel %a2@+, %d1 " ); \
208  asm( "mulul %d2, %d4:%d1 " ); \
209  asm( "addl %d3, %d1 " ); \
210  asm( "addxl %d0, %d4 " ); \
211  asm( "moveq #0, %d3 " ); \
212  asm( "addl %d1, %a3@+ " ); \
213  asm( "addxl %d4, %d3 " );
214 
215 #define MULADDC_STOP \
216  asm( "movl %%d3, %0 " : "=m" (c)); \
217  asm( "movl %%a3, %0 " : "=m" (d)); \
218  asm( "movl %%a2, %0 " : "=m" (s) :: \
219  "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
220 
221 #define MULADDC_HUIT \
222  asm( "movel %a2@+, %d1 " ); \
223  asm( "mulul %d2, %d4:%d1 " ); \
224  asm( "addxl %d3, %d1 " ); \
225  asm( "addxl %d0, %d4 " ); \
226  asm( "addl %d1, %a3@+ " ); \
227  asm( "movel %a2@+, %d1 " ); \
228  asm( "mulul %d2, %d3:%d1 " ); \
229  asm( "addxl %d4, %d1 " ); \
230  asm( "addxl %d0, %d3 " ); \
231  asm( "addl %d1, %a3@+ " ); \
232  asm( "movel %a2@+, %d1 " ); \
233  asm( "mulul %d2, %d4:%d1 " ); \
234  asm( "addxl %d3, %d1 " ); \
235  asm( "addxl %d0, %d4 " ); \
236  asm( "addl %d1, %a3@+ " ); \
237  asm( "movel %a2@+, %d1 " ); \
238  asm( "mulul %d2, %d3:%d1 " ); \
239  asm( "addxl %d4, %d1 " ); \
240  asm( "addxl %d0, %d3 " ); \
241  asm( "addl %d1, %a3@+ " ); \
242  asm( "movel %a2@+, %d1 " ); \
243  asm( "mulul %d2, %d4:%d1 " ); \
244  asm( "addxl %d3, %d1 " ); \
245  asm( "addxl %d0, %d4 " ); \
246  asm( "addl %d1, %a3@+ " ); \
247  asm( "movel %a2@+, %d1 " ); \
248  asm( "mulul %d2, %d3:%d1 " ); \
249  asm( "addxl %d4, %d1 " ); \
250  asm( "addxl %d0, %d3 " ); \
251  asm( "addl %d1, %a3@+ " ); \
252  asm( "movel %a2@+, %d1 " ); \
253  asm( "mulul %d2, %d4:%d1 " ); \
254  asm( "addxl %d3, %d1 " ); \
255  asm( "addxl %d0, %d4 " ); \
256  asm( "addl %d1, %a3@+ " ); \
257  asm( "movel %a2@+, %d1 " ); \
258  asm( "mulul %d2, %d3:%d1 " ); \
259  asm( "addxl %d4, %d1 " ); \
260  asm( "addxl %d0, %d3 " ); \
261  asm( "addl %d1, %a3@+ " ); \
262  asm( "addxl %d0, %d3 " );
263 
264 #endif /* MC68000 */
265 
266 #if defined(__powerpc__) || defined(__ppc__)
267 #if defined(__powerpc64__) || defined(__ppc64__)
268 
269 #if defined(__MACH__) && defined(__APPLE__)
270 
271 #define MULADDC_INIT \
272  asm( "ld r3, %0 " :: "m" (s)); \
273  asm( "ld r4, %0 " :: "m" (d)); \
274  asm( "ld r5, %0 " :: "m" (c)); \
275  asm( "ld r6, %0 " :: "m" (b)); \
276  asm( "addi r3, r3, -8 " ); \
277  asm( "addi r4, r4, -8 " ); \
278  asm( "addic r5, r5, 0 " );
279 
280 #define MULADDC_CORE \
281  asm( "ldu r7, 8(r3) " ); \
282  asm( "mulld r8, r7, r6 " ); \
283  asm( "mulhdu r9, r7, r6 " ); \
284  asm( "adde r8, r8, r5 " ); \
285  asm( "ld r7, 8(r4) " ); \
286  asm( "addze r5, r9 " ); \
287  asm( "addc r8, r8, r7 " ); \
288  asm( "stdu r8, 8(r4) " );
289 
290 #define MULADDC_STOP \
291  asm( "addze r5, r5 " ); \
292  asm( "addi r4, r4, 8 " ); \
293  asm( "addi r3, r3, 8 " ); \
294  asm( "std r5, %0 " : "=m" (c)); \
295  asm( "std r4, %0 " : "=m" (d)); \
296  asm( "std r3, %0 " : "=m" (s) :: \
297  "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
298 
299 #else
300 
301 #define MULADDC_INIT \
302  asm( "ld %%r3, %0 " :: "m" (s)); \
303  asm( "ld %%r4, %0 " :: "m" (d)); \
304  asm( "ld %%r5, %0 " :: "m" (c)); \
305  asm( "ld %%r6, %0 " :: "m" (b)); \
306  asm( "addi %r3, %r3, -8 " ); \
307  asm( "addi %r4, %r4, -8 " ); \
308  asm( "addic %r5, %r5, 0 " );
309 
310 #define MULADDC_CORE \
311  asm( "ldu %r7, 8(%r3) " ); \
312  asm( "mulld %r8, %r7, %r6 " ); \
313  asm( "mulhdu %r9, %r7, %r6 " ); \
314  asm( "adde %r8, %r8, %r5 " ); \
315  asm( "ld %r7, 8(%r4) " ); \
316  asm( "addze %r5, %r9 " ); \
317  asm( "addc %r8, %r8, %r7 " ); \
318  asm( "stdu %r8, 8(%r4) " );
319 
320 #define MULADDC_STOP \
321  asm( "addze %r5, %r5 " ); \
322  asm( "addi %r4, %r4, 8 " ); \
323  asm( "addi %r3, %r3, 8 " ); \
324  asm( "std %%r5, %0 " : "=m" (c)); \
325  asm( "std %%r4, %0 " : "=m" (d)); \
326  asm( "std %%r3, %0 " : "=m" (s) :: \
327  "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
328 
329 #endif
330 
331 #else /* PPC32 */
332 
333 #if defined(__MACH__) && defined(__APPLE__)
334 
335 #define MULADDC_INIT \
336  asm( "lwz r3, %0 " :: "m" (s)); \
337  asm( "lwz r4, %0 " :: "m" (d)); \
338  asm( "lwz r5, %0 " :: "m" (c)); \
339  asm( "lwz r6, %0 " :: "m" (b)); \
340  asm( "addi r3, r3, -4 " ); \
341  asm( "addi r4, r4, -4 " ); \
342  asm( "addic r5, r5, 0 " );
343 
344 #define MULADDC_CORE \
345  asm( "lwzu r7, 4(r3) " ); \
346  asm( "mullw r8, r7, r6 " ); \
347  asm( "mulhwu r9, r7, r6 " ); \
348  asm( "adde r8, r8, r5 " ); \
349  asm( "lwz r7, 4(r4) " ); \
350  asm( "addze r5, r9 " ); \
351  asm( "addc r8, r8, r7 " ); \
352  asm( "stwu r8, 4(r4) " );
353 
354 #define MULADDC_STOP \
355  asm( "addze r5, r5 " ); \
356  asm( "addi r4, r4, 4 " ); \
357  asm( "addi r3, r3, 4 " ); \
358  asm( "stw r5, %0 " : "=m" (c)); \
359  asm( "stw r4, %0 " : "=m" (d)); \
360  asm( "stw r3, %0 " : "=m" (s) :: \
361  "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
362 
363 #else
364 
365 #define MULADDC_INIT \
366  asm( "lwz %%r3, %0 " :: "m" (s)); \
367  asm( "lwz %%r4, %0 " :: "m" (d)); \
368  asm( "lwz %%r5, %0 " :: "m" (c)); \
369  asm( "lwz %%r6, %0 " :: "m" (b)); \
370  asm( "addi %r3, %r3, -4 " ); \
371  asm( "addi %r4, %r4, -4 " ); \
372  asm( "addic %r5, %r5, 0 " );
373 
374 #define MULADDC_CORE \
375  asm( "lwzu %r7, 4(%r3) " ); \
376  asm( "mullw %r8, %r7, %r6 " ); \
377  asm( "mulhwu %r9, %r7, %r6 " ); \
378  asm( "adde %r8, %r8, %r5 " ); \
379  asm( "lwz %r7, 4(%r4) " ); \
380  asm( "addze %r5, %r9 " ); \
381  asm( "addc %r8, %r8, %r7 " ); \
382  asm( "stwu %r8, 4(%r4) " );
383 
384 #define MULADDC_STOP \
385  asm( "addze %r5, %r5 " ); \
386  asm( "addi %r4, %r4, 4 " ); \
387  asm( "addi %r3, %r3, 4 " ); \
388  asm( "stw %%r5, %0 " : "=m" (c)); \
389  asm( "stw %%r4, %0 " : "=m" (d)); \
390  asm( "stw %%r3, %0 " : "=m" (s) :: \
391  "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
392 
393 #endif
394 
395 #endif /* PPC32 */
396 #endif /* PPC64 */
397 
398 #if defined(__sparc__)
399 
400 #define MULADDC_INIT \
401  asm( "ld %0, %%o0 " :: "m" (s)); \
402  asm( "ld %0, %%o1 " :: "m" (d)); \
403  asm( "ld %0, %%o2 " :: "m" (c)); \
404  asm( "ld %0, %%o3 " :: "m" (b));
405 
406 #define MULADDC_CORE \
407  asm( "ld [%o0], %o4 " ); \
408  asm( "inc 4, %o0 " ); \
409  asm( "ld [%o1], %o5 " ); \
410  asm( "umul %o3, %o4, %o4 " ); \
411  asm( "addcc %o4, %o2, %o4 " ); \
412  asm( "rd %y, %g1 " ); \
413  asm( "addx %g1, 0, %g1 " ); \
414  asm( "addcc %o4, %o5, %o4 " ); \
415  asm( "st %o4, [%o1] " ); \
416  asm( "addx %g1, 0, %o2 " ); \
417  asm( "inc 4, %o1 " );
418 
419 #define MULADDC_STOP \
420  asm( "st %%o2, %0 " : "=m" (c)); \
421  asm( "st %%o1, %0 " : "=m" (d)); \
422  asm( "st %%o0, %0 " : "=m" (s) :: \
423  "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
424 
425 #endif /* SPARCv8 */
426 
427 #if defined(__microblaze__) || defined(microblaze)
428 
429 #define MULADDC_INIT \
430  asm( "lwi r3, %0 " :: "m" (s)); \
431  asm( "lwi r4, %0 " :: "m" (d)); \
432  asm( "lwi r5, %0 " :: "m" (c)); \
433  asm( "lwi r6, %0 " :: "m" (b)); \
434  asm( "andi r7, r6, 0xffff" ); \
435  asm( "bsrli r6, r6, 16 " );
436 
437 #define MULADDC_CORE \
438  asm( "lhui r8, r3, 0 " ); \
439  asm( "addi r3, r3, 2 " ); \
440  asm( "lhui r9, r3, 0 " ); \
441  asm( "addi r3, r3, 2 " ); \
442  asm( "mul r10, r9, r6 " ); \
443  asm( "mul r11, r8, r7 " ); \
444  asm( "mul r12, r9, r7 " ); \
445  asm( "mul r13, r8, r6 " ); \
446  asm( "bsrli r8, r10, 16 " ); \
447  asm( "bsrli r9, r11, 16 " ); \
448  asm( "add r13, r13, r8 " ); \
449  asm( "add r13, r13, r9 " ); \
450  asm( "bslli r10, r10, 16 " ); \
451  asm( "bslli r11, r11, 16 " ); \
452  asm( "add r12, r12, r10 " ); \
453  asm( "addc r13, r13, r0 " ); \
454  asm( "add r12, r12, r11 " ); \
455  asm( "addc r13, r13, r0 " ); \
456  asm( "lwi r10, r4, 0 " ); \
457  asm( "add r12, r12, r10 " ); \
458  asm( "addc r13, r13, r0 " ); \
459  asm( "add r12, r12, r5 " ); \
460  asm( "addc r5, r13, r0 " ); \
461  asm( "swi r12, r4, 0 " ); \
462  asm( "addi r4, r4, 4 " );
463 
464 #define MULADDC_STOP \
465  asm( "swi r5, %0 " : "=m" (c)); \
466  asm( "swi r4, %0 " : "=m" (d)); \
467  asm( "swi r3, %0 " : "=m" (s) :: \
468  "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
469  "r9", "r10", "r11", "r12", "r13" );
470 
471 #endif /* MicroBlaze */
472 
473 #if defined(__tricore__)
474 
475 #define MULADDC_INIT \
476  asm( "ld.a %%a2, %0 " :: "m" (s)); \
477  asm( "ld.a %%a3, %0 " :: "m" (d)); \
478  asm( "ld.w %%d4, %0 " :: "m" (c)); \
479  asm( "ld.w %%d1, %0 " :: "m" (b)); \
480  asm( "xor %d5, %d5 " );
481 
482 #define MULADDC_CORE \
483  asm( "ld.w %d0, [%a2+] " ); \
484  asm( "madd.u %e2, %e4, %d0, %d1 " ); \
485  asm( "ld.w %d0, [%a3] " ); \
486  asm( "addx %d2, %d2, %d0 " ); \
487  asm( "addc %d3, %d3, 0 " ); \
488  asm( "mov %d4, %d3 " ); \
489  asm( "st.w [%a3+], %d2 " );
490 
491 #define MULADDC_STOP \
492  asm( "st.w %0, %%d4 " : "=m" (c)); \
493  asm( "st.a %0, %%a3 " : "=m" (d)); \
494  asm( "st.a %0, %%a2 " : "=m" (s) :: \
495  "d0", "d1", "e2", "d4", "a2", "a3" );
496 
497 #endif /* TriCore */
498 
499 #if defined(__arm__)
500 
501 #if !defined(__thumb__)
502 
503 #define MULADDC_INIT \
504  asm( "ldr r0, %0 " :: "m" (s)); \
505  asm( "ldr r1, %0 " :: "m" (d)); \
506  asm( "ldr r2, %0 " :: "m" (c)); \
507  asm( "ldr r3, %0 " :: "m" (b));
508 
509 #define MULADDC_CORE \
510  asm( "ldr r4, [r0], #4 " ); \
511  asm( "mov r5, #0 " ); \
512  asm( "ldr r6, [r1] " ); \
513  asm( "umlal r2, r5, r3, r4 " ); \
514  asm( "adds r7, r6, r2 " ); \
515  asm( "adc r2, r5, #0 " ); \
516  asm( "str r7, [r1], #4 " );
517 
518 #define MULADDC_STOP \
519  asm( "str r2, %0 " : "=m" (c)); \
520  asm( "str r1, %0 " : "=m" (d)); \
521  asm( "str r0, %0 " : "=m" (s) :: \
522  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
523 
524 #endif /* Thumb */
525 
526 #endif /* ARMv3 */
527 
528 #if defined(__alpha__)
529 
530 #define MULADDC_INIT \
531  asm( "ldq $1, %0 " :: "m" (s)); \
532  asm( "ldq $2, %0 " :: "m" (d)); \
533  asm( "ldq $3, %0 " :: "m" (c)); \
534  asm( "ldq $4, %0 " :: "m" (b));
535 
536 #define MULADDC_CORE \
537  asm( "ldq $6, 0($1) " ); \
538  asm( "addq $1, 8, $1 " ); \
539  asm( "mulq $6, $4, $7 " ); \
540  asm( "umulh $6, $4, $6 " ); \
541  asm( "addq $7, $3, $7 " ); \
542  asm( "cmpult $7, $3, $3 " ); \
543  asm( "ldq $5, 0($2) " ); \
544  asm( "addq $7, $5, $7 " ); \
545  asm( "cmpult $7, $5, $5 " ); \
546  asm( "stq $7, 0($2) " ); \
547  asm( "addq $2, 8, $2 " ); \
548  asm( "addq $6, $3, $3 " ); \
549  asm( "addq $5, $3, $3 " );
550 
551 #define MULADDC_STOP \
552  asm( "stq $3, %0 " : "=m" (c)); \
553  asm( "stq $2, %0 " : "=m" (d)); \
554  asm( "stq $1, %0 " : "=m" (s) :: \
555  "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
556 
557 #endif /* Alpha */
558 
559 #if defined(__mips__)
560 
561 #define MULADDC_INIT \
562  asm( "lw $10, %0 " :: "m" (s)); \
563  asm( "lw $11, %0 " :: "m" (d)); \
564  asm( "lw $12, %0 " :: "m" (c)); \
565  asm( "lw $13, %0 " :: "m" (b));
566 
567 #define MULADDC_CORE \
568  asm( "lw $14, 0($10) " ); \
569  asm( "multu $13, $14 " ); \
570  asm( "addi $10, $10, 4 " ); \
571  asm( "mflo $14 " ); \
572  asm( "mfhi $9 " ); \
573  asm( "addu $14, $12, $14 " ); \
574  asm( "lw $15, 0($11) " ); \
575  asm( "sltu $12, $14, $12 " ); \
576  asm( "addu $15, $14, $15 " ); \
577  asm( "sltu $14, $15, $14 " ); \
578  asm( "addu $12, $12, $9 " ); \
579  asm( "sw $15, 0($11) " ); \
580  asm( "addu $12, $12, $14 " ); \
581  asm( "addi $11, $11, 4 " );
582 
583 #define MULADDC_STOP \
584  asm( "sw $12, %0 " : "=m" (c)); \
585  asm( "sw $11, %0 " : "=m" (d)); \
586  asm( "sw $10, %0 " : "=m" (s) :: \
587  "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
588 
589 #endif /* MIPS */
590 #endif /* GNUC */
591 
592 #if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
593 
594 #define MULADDC_INIT \
595  __asm mov esi, s \
596  __asm mov edi, d \
597  __asm mov ecx, c \
598  __asm mov ebx, b
599 
600 #define MULADDC_CORE \
601  __asm lodsd \
602  __asm mul ebx \
603  __asm add eax, ecx \
604  __asm adc edx, 0 \
605  __asm add eax, [edi] \
606  __asm adc edx, 0 \
607  __asm mov ecx, edx \
608  __asm stosd
609 
610 #if defined(POLARSSL_HAVE_SSE2)
611 
612 #define EMIT __asm _emit
613 
614 #define MULADDC_HUIT \
615  EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
616  EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
617  EMIT 0x0F EMIT 0x6E EMIT 0x1F \
618  EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
619  EMIT 0x0F EMIT 0x6E EMIT 0x16 \
620  EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
621  EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
622  EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
623  EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
624  EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
625  EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
626  EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
627  EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
628  EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
629  EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
630  EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
631  EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
632  EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
633  EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
634  EMIT 0x0F EMIT 0x7E EMIT 0x0F \
635  EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
636  EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
637  EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
638  EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
639  EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
640  EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
641  EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
642  EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
643  EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
644  EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
645  EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
646  EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
647  EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
648  EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
649  EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
650  EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
651  EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
652  EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
653  EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
654  EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
655  EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
656  EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
657  EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
658  EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
659  EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
660  EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
661  EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
662  EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
663  EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
664  EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
665  EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
666  EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
667  EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
668  EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
669  EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
670  EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
671  EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
672  EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
673  EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
674  EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
675  EMIT 0x0F EMIT 0x7E EMIT 0xC9
676 
677 #define MULADDC_STOP \
678  EMIT 0x0F EMIT 0x77 \
679  __asm mov c, ecx \
680  __asm mov d, edi \
681  __asm mov s, esi \
682 
683 #else
684 
685 #define MULADDC_STOP \
686  __asm mov c, ecx \
687  __asm mov d, edi \
688  __asm mov s, esi \
689 
690 #endif /* SSE2 */
691 #endif /* MSVC */
692 
693 #endif /* POLARSSL_HAVE_ASM */
694 
695 #if !defined(MULADDC_CORE)
696 #if defined(POLARSSL_HAVE_LONGLONG)
697 
698 #define MULADDC_INIT \
699 { \
700  t_udbl r; \
701  t_uint r0, r1;
702 
703 #define MULADDC_CORE \
704  r = *(s++) * (t_udbl) b; \
705  r0 = r; \
706  r1 = r >> biL; \
707  r0 += c; r1 += (r0 < c); \
708  r0 += *d; r1 += (r0 < *d); \
709  c = r1; *(d++) = r0;
710 
711 #define MULADDC_STOP \
712 }
713 
714 #else
715 #define MULADDC_INIT \
716 { \
717  t_uint s0, s1, b0, b1; \
718  t_uint r0, r1, rx, ry; \
719  b0 = ( b << biH ) >> biH; \
720  b1 = ( b >> biH );
721 
722 #define MULADDC_CORE \
723  s0 = ( *s << biH ) >> biH; \
724  s1 = ( *s >> biH ); s++; \
725  rx = s0 * b1; r0 = s0 * b0; \
726  ry = s1 * b0; r1 = s1 * b1; \
727  r1 += ( rx >> biH ); \
728  r1 += ( ry >> biH ); \
729  rx <<= biH; ry <<= biH; \
730  r0 += rx; r1 += (r0 < rx); \
731  r0 += ry; r1 += (r0 < ry); \
732  r0 += c; r1 += (r0 < c); \
733  r0 += *d; r1 += (r0 < *d); \
734  c = r1; *(d++) = r0;
735 
736 #define MULADDC_STOP \
737 }
738 
739 #endif /* C (generic) */
740 #endif /* C (longlong) */
741 
742 #endif /* bn_mul.h */