PolarSSL v1.1.4
bn_mul.h
Go to the documentation of this file.
00001 
00027 /*
00028  *      Multiply source vector [s] with b, add result
00029  *       to destination vector [d] and set carry c.
00030  *
00031  *      Currently supports:
00032  *
00033  *         . IA-32 (386+)         . AMD64 / EM64T
00034  *         . IA-32 (SSE2)         . Motorola 68000
00035  *         . PowerPC, 32-bit      . MicroBlaze
00036  *         . PowerPC, 64-bit      . TriCore
00037  *         . SPARC v8             . ARM v3+
00038  *         . Alpha                . MIPS32
00039  *         . C, longlong          . C, generic
00040  */
00041 #ifndef POLARSSL_BN_MUL_H
00042 #define POLARSSL_BN_MUL_H
00043 
00044 #include "bignum.h"
00045 
00046 #if defined(POLARSSL_HAVE_ASM)
00047 
00048 #if defined(__GNUC__)
00049 #if defined(__i386__)
00050 
00051 #define MULADDC_INIT                \
00052     asm( "                          \
00053         movl   %%ebx, %0;           \
00054         movl   %5, %%esi;           \
00055         movl   %6, %%edi;           \
00056         movl   %7, %%ecx;           \
00057         movl   %8, %%ebx;           \
00058         "
00059 
00060 #define MULADDC_CORE                \
00061         "                           \
00062         lodsl;                      \
00063         mull   %%ebx;               \
00064         addl   %%ecx,   %%eax;      \
00065         adcl   $0,      %%edx;      \
00066         addl   (%%edi), %%eax;      \
00067         adcl   $0,      %%edx;      \
00068         movl   %%edx,   %%ecx;      \
00069         stosl;                      \
00070         "
00071 
00072 #if defined(POLARSSL_HAVE_SSE2)
00073 
00074 #define MULADDC_HUIT                    \
00075         "                               \
00076         movd     %%ecx,     %%mm1;      \
00077         movd     %%ebx,     %%mm0;      \
00078         movd     (%%edi),   %%mm3;      \
00079         paddq    %%mm3,     %%mm1;      \
00080         movd     (%%esi),   %%mm2;      \
00081         pmuludq  %%mm0,     %%mm2;      \
00082         movd     4(%%esi),  %%mm4;      \
00083         pmuludq  %%mm0,     %%mm4;      \
00084         movd     8(%%esi),  %%mm6;      \
00085         pmuludq  %%mm0,     %%mm6;      \
00086         movd     12(%%esi), %%mm7;      \
00087         pmuludq  %%mm0,     %%mm7;      \
00088         paddq    %%mm2,     %%mm1;      \
00089         movd     4(%%edi),  %%mm3;      \
00090         paddq    %%mm4,     %%mm3;      \
00091         movd     8(%%edi),  %%mm5;      \
00092         paddq    %%mm6,     %%mm5;      \
00093         movd     12(%%edi), %%mm4;      \
00094         paddq    %%mm4,     %%mm7;      \
00095         movd     %%mm1,     (%%edi);    \
00096         movd     16(%%esi), %%mm2;      \
00097         pmuludq  %%mm0,     %%mm2;      \
00098         psrlq    $32,       %%mm1;      \
00099         movd     20(%%esi), %%mm4;      \
00100         pmuludq  %%mm0,     %%mm4;      \
00101         paddq    %%mm3,     %%mm1;      \
00102         movd     24(%%esi), %%mm6;      \
00103         pmuludq  %%mm0,     %%mm6;      \
00104         movd     %%mm1,     4(%%edi);   \
00105         psrlq    $32,       %%mm1;      \
00106         movd     28(%%esi), %%mm3;      \
00107         pmuludq  %%mm0,     %%mm3;      \
00108         paddq    %%mm5,     %%mm1;      \
00109         movd     16(%%edi), %%mm5;      \
00110         paddq    %%mm5,     %%mm2;      \
00111         movd     %%mm1,     8(%%edi);   \
00112         psrlq    $32,       %%mm1;      \
00113         paddq    %%mm7,     %%mm1;      \
00114         movd     20(%%edi), %%mm5;      \
00115         paddq    %%mm5,     %%mm4;      \
00116         movd     %%mm1,     12(%%edi);  \
00117         psrlq    $32,       %%mm1;      \
00118         paddq    %%mm2,     %%mm1;      \
00119         movd     24(%%edi), %%mm5;      \
00120         paddq    %%mm5,     %%mm6;      \
00121         movd     %%mm1,     16(%%edi);  \
00122         psrlq    $32,       %%mm1;      \
00123         paddq    %%mm4,     %%mm1;      \
00124         movd     28(%%edi), %%mm5;      \
00125         paddq    %%mm5,     %%mm3;      \
00126         movd     %%mm1,     20(%%edi);  \
00127         psrlq    $32,       %%mm1;      \
00128         paddq    %%mm6,     %%mm1;      \
00129         movd     %%mm1,     24(%%edi);  \
00130         psrlq    $32,       %%mm1;      \
00131         paddq    %%mm3,     %%mm1;      \
00132         movd     %%mm1,     28(%%edi);  \
00133         addl     $32,       %%edi;      \
00134         addl     $32,       %%esi;      \
00135         psrlq    $32,       %%mm1;      \
00136         movd     %%mm1,     %%ecx;      \
00137         "
00138 
00139 #define MULADDC_STOP            \
00140         "                       \
00141         emms;                   \
00142         movl   %4, %%ebx;       \
00143         movl   %%ecx, %1;       \
00144         movl   %%edi, %2;       \
00145         movl   %%esi, %3;       \
00146         "                       \
00147         : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
00148         : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
00149         : "eax", "ecx", "edx", "esi", "edi"             \
00150     );
00151 
00152 #else
00153 
00154 #define MULADDC_STOP            \
00155         "                       \
00156         movl   %4, %%ebx;       \
00157         movl   %%ecx, %1;       \
00158         movl   %%edi, %2;       \
00159         movl   %%esi, %3;       \
00160         "                       \
00161         : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
00162         : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
00163         : "eax", "ecx", "edx", "esi", "edi"             \
00164     );
00165 #endif /* SSE2 */
00166 #endif /* i386 */
00167 
00168 #if defined(__amd64__) || defined (__x86_64__)
00169 
00170 #define MULADDC_INIT                            \
00171     asm( "movq   %0, %%rsi      " :: "m" (s));  \
00172     asm( "movq   %0, %%rdi      " :: "m" (d));  \
00173     asm( "movq   %0, %%rcx      " :: "m" (c));  \
00174     asm( "movq   %0, %%rbx      " :: "m" (b));  \
00175     asm( "xorq   %r8, %r8       " );
00176 
00177 #define MULADDC_CORE                            \
00178     asm( "movq  (%rsi),%rax     " );            \
00179     asm( "mulq   %rbx           " );            \
00180     asm( "addq   $8,   %rsi     " );            \
00181     asm( "addq   %rcx, %rax     " );            \
00182     asm( "movq   %r8,  %rcx     " );            \
00183     asm( "adcq   $0,   %rdx     " );            \
00184     asm( "nop                   " );            \
00185     asm( "addq   %rax, (%rdi)   " );            \
00186     asm( "adcq   %rdx, %rcx     " );            \
00187     asm( "addq   $8,   %rdi     " );
00188 
00189 #define MULADDC_STOP                            \
00190     asm( "movq   %%rcx, %0      " : "=m" (c));  \
00191     asm( "movq   %%rdi, %0      " : "=m" (d));  \
00192     asm( "movq   %%rsi, %0      " : "=m" (s) :: \
00193     "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
00194 
00195 #endif /* AMD64 */
00196 
00197 #if defined(__mc68020__) || defined(__mcpu32__)
00198 
00199 #define MULADDC_INIT                            \
00200     asm( "movl   %0, %%a2       " :: "m" (s));  \
00201     asm( "movl   %0, %%a3       " :: "m" (d));  \
00202     asm( "movl   %0, %%d3       " :: "m" (c));  \
00203     asm( "movl   %0, %%d2       " :: "m" (b));  \
00204     asm( "moveq  #0, %d0        " );
00205 
00206 #define MULADDC_CORE                            \
00207     asm( "movel  %a2@+, %d1     " );            \
00208     asm( "mulul  %d2, %d4:%d1   " );            \
00209     asm( "addl   %d3, %d1       " );            \
00210     asm( "addxl  %d0, %d4       " );            \
00211     asm( "moveq  #0,  %d3       " );            \
00212     asm( "addl   %d1, %a3@+     " );            \
00213     asm( "addxl  %d4, %d3       " );
00214 
00215 #define MULADDC_STOP                            \
00216     asm( "movl   %%d3, %0       " : "=m" (c));  \
00217     asm( "movl   %%a3, %0       " : "=m" (d));  \
00218     asm( "movl   %%a2, %0       " : "=m" (s) :: \
00219     "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
00220 
00221 #define MULADDC_HUIT                            \
00222     asm( "movel  %a2@+, %d1     " );            \
00223     asm( "mulul  %d2, %d4:%d1   " );            \
00224     asm( "addxl  %d3, %d1       " );            \
00225     asm( "addxl  %d0, %d4       " );            \
00226     asm( "addl   %d1, %a3@+     " );            \
00227     asm( "movel  %a2@+, %d1     " );            \
00228     asm( "mulul  %d2, %d3:%d1   " );            \
00229     asm( "addxl  %d4, %d1       " );            \
00230     asm( "addxl  %d0, %d3       " );            \
00231     asm( "addl   %d1, %a3@+     " );            \
00232     asm( "movel  %a2@+, %d1     " );            \
00233     asm( "mulul  %d2, %d4:%d1   " );            \
00234     asm( "addxl  %d3, %d1       " );            \
00235     asm( "addxl  %d0, %d4       " );            \
00236     asm( "addl   %d1, %a3@+     " );            \
00237     asm( "movel  %a2@+, %d1     " );            \
00238     asm( "mulul  %d2, %d3:%d1   " );            \
00239     asm( "addxl  %d4, %d1       " );            \
00240     asm( "addxl  %d0, %d3       " );            \
00241     asm( "addl   %d1, %a3@+     " );            \
00242     asm( "movel  %a2@+, %d1     " );            \
00243     asm( "mulul  %d2, %d4:%d1   " );            \
00244     asm( "addxl  %d3, %d1       " );            \
00245     asm( "addxl  %d0, %d4       " );            \
00246     asm( "addl   %d1, %a3@+     " );            \
00247     asm( "movel  %a2@+, %d1     " );            \
00248     asm( "mulul  %d2, %d3:%d1   " );            \
00249     asm( "addxl  %d4, %d1       " );            \
00250     asm( "addxl  %d0, %d3       " );            \
00251     asm( "addl   %d1, %a3@+     " );            \
00252     asm( "movel  %a2@+, %d1     " );            \
00253     asm( "mulul  %d2, %d4:%d1   " );            \
00254     asm( "addxl  %d3, %d1       " );            \
00255     asm( "addxl  %d0, %d4       " );            \
00256     asm( "addl   %d1, %a3@+     " );            \
00257     asm( "movel  %a2@+, %d1     " );            \
00258     asm( "mulul  %d2, %d3:%d1   " );            \
00259     asm( "addxl  %d4, %d1       " );            \
00260     asm( "addxl  %d0, %d3       " );            \
00261     asm( "addl   %d1, %a3@+     " );            \
00262     asm( "addxl  %d0, %d3       " );
00263 
00264 #endif /* MC68000 */
00265 
00266 #if defined(__powerpc__)   || defined(__ppc__)
00267 #if defined(__powerpc64__) || defined(__ppc64__)
00268 
00269 #if defined(__MACH__) && defined(__APPLE__)
00270 
00271 #define MULADDC_INIT                            \
00272     asm( "ld     r3, %0         " :: "m" (s));  \
00273     asm( "ld     r4, %0         " :: "m" (d));  \
00274     asm( "ld     r5, %0         " :: "m" (c));  \
00275     asm( "ld     r6, %0         " :: "m" (b));  \
00276     asm( "addi   r3, r3, -8     " );            \
00277     asm( "addi   r4, r4, -8     " );            \
00278     asm( "addic  r5, r5,  0     " );
00279 
00280 #define MULADDC_CORE                            \
00281     asm( "ldu    r7, 8(r3)      " );            \
00282     asm( "mulld  r8, r7, r6     " );            \
00283     asm( "mulhdu r9, r7, r6     " );            \
00284     asm( "adde   r8, r8, r5     " );            \
00285     asm( "ld     r7, 8(r4)      " );            \
00286     asm( "addze  r5, r9         " );            \
00287     asm( "addc   r8, r8, r7     " );            \
00288     asm( "stdu   r8, 8(r4)      " );
00289 
00290 #define MULADDC_STOP                            \
00291     asm( "addze  r5, r5         " );            \
00292     asm( "addi   r4, r4, 8      " );            \
00293     asm( "addi   r3, r3, 8      " );            \
00294     asm( "std    r5, %0         " : "=m" (c));  \
00295     asm( "std    r4, %0         " : "=m" (d));  \
00296     asm( "std    r3, %0         " : "=m" (s) :: \
00297     "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
00298 
00299 #else
00300 
00301 #define MULADDC_INIT                            \
00302     asm( "ld     %%r3, %0       " :: "m" (s));  \
00303     asm( "ld     %%r4, %0       " :: "m" (d));  \
00304     asm( "ld     %%r5, %0       " :: "m" (c));  \
00305     asm( "ld     %%r6, %0       " :: "m" (b));  \
00306     asm( "addi   %r3, %r3, -8   " );            \
00307     asm( "addi   %r4, %r4, -8   " );            \
00308     asm( "addic  %r5, %r5,  0   " );
00309 
00310 #define MULADDC_CORE                            \
00311     asm( "ldu    %r7, 8(%r3)    " );            \
00312     asm( "mulld  %r8, %r7, %r6  " );            \
00313     asm( "mulhdu %r9, %r7, %r6  " );            \
00314     asm( "adde   %r8, %r8, %r5  " );            \
00315     asm( "ld     %r7, 8(%r4)    " );            \
00316     asm( "addze  %r5, %r9       " );            \
00317     asm( "addc   %r8, %r8, %r7  " );            \
00318     asm( "stdu   %r8, 8(%r4)    " );
00319 
00320 #define MULADDC_STOP                            \
00321     asm( "addze  %r5, %r5       " );            \
00322     asm( "addi   %r4, %r4, 8    " );            \
00323     asm( "addi   %r3, %r3, 8    " );            \
00324     asm( "std    %%r5, %0       " : "=m" (c));  \
00325     asm( "std    %%r4, %0       " : "=m" (d));  \
00326     asm( "std    %%r3, %0       " : "=m" (s) :: \
00327     "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
00328 
00329 #endif
00330 
00331 #else /* PPC32 */
00332 
00333 #if defined(__MACH__) && defined(__APPLE__)
00334 
00335 #define MULADDC_INIT                            \
00336     asm( "lwz    r3, %0         " :: "m" (s));  \
00337     asm( "lwz    r4, %0         " :: "m" (d));  \
00338     asm( "lwz    r5, %0         " :: "m" (c));  \
00339     asm( "lwz    r6, %0         " :: "m" (b));  \
00340     asm( "addi   r3, r3, -4     " );            \
00341     asm( "addi   r4, r4, -4     " );            \
00342     asm( "addic  r5, r5,  0     " );
00343 
00344 #define MULADDC_CORE                            \
00345     asm( "lwzu   r7, 4(r3)      " );            \
00346     asm( "mullw  r8, r7, r6     " );            \
00347     asm( "mulhwu r9, r7, r6     " );            \
00348     asm( "adde   r8, r8, r5     " );            \
00349     asm( "lwz    r7, 4(r4)      " );            \
00350     asm( "addze  r5, r9         " );            \
00351     asm( "addc   r8, r8, r7     " );            \
00352     asm( "stwu   r8, 4(r4)      " );
00353 
00354 #define MULADDC_STOP                            \
00355     asm( "addze  r5, r5         " );            \
00356     asm( "addi   r4, r4, 4      " );            \
00357     asm( "addi   r3, r3, 4      " );            \
00358     asm( "stw    r5, %0         " : "=m" (c));  \
00359     asm( "stw    r4, %0         " : "=m" (d));  \
00360     asm( "stw    r3, %0         " : "=m" (s) :: \
00361     "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
00362 
00363 #else
00364 
00365 #define MULADDC_INIT                            \
00366     asm( "lwz    %%r3, %0       " :: "m" (s));  \
00367     asm( "lwz    %%r4, %0       " :: "m" (d));  \
00368     asm( "lwz    %%r5, %0       " :: "m" (c));  \
00369     asm( "lwz    %%r6, %0       " :: "m" (b));  \
00370     asm( "addi   %r3, %r3, -4   " );            \
00371     asm( "addi   %r4, %r4, -4   " );            \
00372     asm( "addic  %r5, %r5,  0   " );
00373 
00374 #define MULADDC_CORE                            \
00375     asm( "lwzu   %r7, 4(%r3)    " );            \
00376     asm( "mullw  %r8, %r7, %r6  " );            \
00377     asm( "mulhwu %r9, %r7, %r6  " );            \
00378     asm( "adde   %r8, %r8, %r5  " );            \
00379     asm( "lwz    %r7, 4(%r4)    " );            \
00380     asm( "addze  %r5, %r9       " );            \
00381     asm( "addc   %r8, %r8, %r7  " );            \
00382     asm( "stwu   %r8, 4(%r4)    " );
00383 
00384 #define MULADDC_STOP                            \
00385     asm( "addze  %r5, %r5       " );            \
00386     asm( "addi   %r4, %r4, 4    " );            \
00387     asm( "addi   %r3, %r3, 4    " );            \
00388     asm( "stw    %%r5, %0       " : "=m" (c));  \
00389     asm( "stw    %%r4, %0       " : "=m" (d));  \
00390     asm( "stw    %%r3, %0       " : "=m" (s) :: \
00391     "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
00392 
00393 #endif
00394 
00395 #endif /* PPC32 */
00396 #endif /* PPC64 */
00397 
00398 #if defined(__sparc__)
00399 
00400 #define MULADDC_INIT                            \
00401     asm( "ld     %0, %%o0       " :: "m" (s));  \
00402     asm( "ld     %0, %%o1       " :: "m" (d));  \
00403     asm( "ld     %0, %%o2       " :: "m" (c));  \
00404     asm( "ld     %0, %%o3       " :: "m" (b));
00405 
00406 #define MULADDC_CORE                            \
00407     asm( "ld    [%o0], %o4      " );            \
00408     asm( "inc      4,  %o0      " );            \
00409     asm( "ld    [%o1], %o5      " );            \
00410     asm( "umul   %o3,  %o4, %o4 " );            \
00411     asm( "addcc  %o4,  %o2, %o4 " );            \
00412     asm( "rd      %y,  %g1      " );            \
00413     asm( "addx   %g1,    0, %g1 " );            \
00414     asm( "addcc  %o4,  %o5, %o4 " );            \
00415     asm( "st     %o4, [%o1]     " );            \
00416     asm( "addx   %g1,    0, %o2 " );            \
00417     asm( "inc      4,  %o1      " );
00418 
00419 #define MULADDC_STOP                            \
00420     asm( "st     %%o2, %0       " : "=m" (c));  \
00421     asm( "st     %%o1, %0       " : "=m" (d));  \
00422     asm( "st     %%o0, %0       " : "=m" (s) :: \
00423     "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
00424 
00425 #endif /* SPARCv8 */
00426 
00427 #if defined(__microblaze__) || defined(microblaze)
00428 
00429 #define MULADDC_INIT                            \
00430     asm( "lwi   r3,   %0        " :: "m" (s));  \
00431     asm( "lwi   r4,   %0        " :: "m" (d));  \
00432     asm( "lwi   r5,   %0        " :: "m" (c));  \
00433     asm( "lwi   r6,   %0        " :: "m" (b));  \
00434     asm( "andi  r7,   r6, 0xffff" );            \
00435     asm( "bsrli r6,   r6, 16    " );
00436 
00437 #define MULADDC_CORE                            \
00438     asm( "lhui  r8,   r3,   0   " );            \
00439     asm( "addi  r3,   r3,   2   " );            \
00440     asm( "lhui  r9,   r3,   0   " );            \
00441     asm( "addi  r3,   r3,   2   " );            \
00442     asm( "mul   r10,  r9,  r6   " );            \
00443     asm( "mul   r11,  r8,  r7   " );            \
00444     asm( "mul   r12,  r9,  r7   " );            \
00445     asm( "mul   r13,  r8,  r6   " );            \
00446     asm( "bsrli  r8, r10,  16   " );            \
00447     asm( "bsrli  r9, r11,  16   " );            \
00448     asm( "add   r13, r13,  r8   " );            \
00449     asm( "add   r13, r13,  r9   " );            \
00450     asm( "bslli r10, r10,  16   " );            \
00451     asm( "bslli r11, r11,  16   " );            \
00452     asm( "add   r12, r12, r10   " );            \
00453     asm( "addc  r13, r13,  r0   " );            \
00454     asm( "add   r12, r12, r11   " );            \
00455     asm( "addc  r13, r13,  r0   " );            \
00456     asm( "lwi   r10,  r4,   0   " );            \
00457     asm( "add   r12, r12, r10   " );            \
00458     asm( "addc  r13, r13,  r0   " );            \
00459     asm( "add   r12, r12,  r5   " );            \
00460     asm( "addc   r5, r13,  r0   " );            \
00461     asm( "swi   r12,  r4,   0   " );            \
00462     asm( "addi   r4,  r4,   4   " );
00463 
00464 #define MULADDC_STOP                            \
00465     asm( "swi   r5,   %0        " : "=m" (c));  \
00466     asm( "swi   r4,   %0        " : "=m" (d));  \
00467     asm( "swi   r3,   %0        " : "=m" (s) :: \
00468      "r3", "r4" , "r5" , "r6" , "r7" , "r8" ,   \
00469      "r9", "r10", "r11", "r12", "r13" );
00470 
00471 #endif /* MicroBlaze */
00472 
00473 #if defined(__tricore__)
00474 
00475 #define MULADDC_INIT                            \
00476     asm( "ld.a   %%a2, %0       " :: "m" (s));  \
00477     asm( "ld.a   %%a3, %0       " :: "m" (d));  \
00478     asm( "ld.w   %%d4, %0       " :: "m" (c));  \
00479     asm( "ld.w   %%d1, %0       " :: "m" (b));  \
00480     asm( "xor    %d5, %d5       " );
00481 
00482 #define MULADDC_CORE                            \
00483     asm( "ld.w   %d0,   [%a2+]      " );        \
00484     asm( "madd.u %e2, %e4, %d0, %d1 " );        \
00485     asm( "ld.w   %d0,   [%a3]       " );        \
00486     asm( "addx   %d2,    %d2,  %d0  " );        \
00487     asm( "addc   %d3,    %d3,    0  " );        \
00488     asm( "mov    %d4,    %d3        " );        \
00489     asm( "st.w  [%a3+],  %d2        " );
00490 
00491 #define MULADDC_STOP                            \
00492     asm( "st.w   %0, %%d4       " : "=m" (c));  \
00493     asm( "st.a   %0, %%a3       " : "=m" (d));  \
00494     asm( "st.a   %0, %%a2       " : "=m" (s) :: \
00495     "d0", "d1", "e2", "d4", "a2", "a3" );
00496 
00497 #endif /* TriCore */
00498 
00499 #if defined(__arm__)
00500 
00501 #if !defined(__thumb__)
00502 
00503 #define MULADDC_INIT                            \
00504     asm( "ldr    r0, %0         " :: "m" (s));  \
00505     asm( "ldr    r1, %0         " :: "m" (d));  \
00506     asm( "ldr    r2, %0         " :: "m" (c));  \
00507     asm( "ldr    r3, %0         " :: "m" (b));
00508 
00509 #define MULADDC_CORE                            \
00510     asm( "ldr    r4, [r0], #4   " );            \
00511     asm( "mov    r5, #0         " );            \
00512     asm( "ldr    r6, [r1]       " );            \
00513     asm( "umlal  r2, r5, r3, r4 " );            \
00514     asm( "adds   r7, r6, r2     " );            \
00515     asm( "adc    r2, r5, #0     " );            \
00516     asm( "str    r7, [r1], #4   " );
00517 
00518 #define MULADDC_STOP                            \
00519     asm( "str    r2, %0         " : "=m" (c));  \
00520     asm( "str    r1, %0         " : "=m" (d));  \
00521     asm( "str    r0, %0         " : "=m" (s) :: \
00522     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
00523 
00524 #endif /* Thumb */
00525 
00526 #endif /* ARMv3 */
00527 
00528 #if defined(__alpha__)
00529 
00530 #define MULADDC_INIT                            \
00531     asm( "ldq    $1, %0         " :: "m" (s));  \
00532     asm( "ldq    $2, %0         " :: "m" (d));  \
00533     asm( "ldq    $3, %0         " :: "m" (c));  \
00534     asm( "ldq    $4, %0         " :: "m" (b));
00535 
00536 #define MULADDC_CORE                            \
00537     asm( "ldq    $6,  0($1)     " );            \
00538     asm( "addq   $1,  8, $1     " );            \
00539     asm( "mulq   $6, $4, $7     " );            \
00540     asm( "umulh  $6, $4, $6     " );            \
00541     asm( "addq   $7, $3, $7     " );            \
00542     asm( "cmpult $7, $3, $3     " );            \
00543     asm( "ldq    $5,  0($2)     " );            \
00544     asm( "addq   $7, $5, $7     " );            \
00545     asm( "cmpult $7, $5, $5     " );            \
00546     asm( "stq    $7,  0($2)     " );            \
00547     asm( "addq   $2,  8, $2     " );            \
00548     asm( "addq   $6, $3, $3     " );            \
00549     asm( "addq   $5, $3, $3     " );
00550 
00551 #define MULADDC_STOP                            \
00552     asm( "stq    $3, %0         " : "=m" (c));  \
00553     asm( "stq    $2, %0         " : "=m" (d));  \
00554     asm( "stq    $1, %0         " : "=m" (s) :: \
00555     "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
00556 
00557 #endif /* Alpha */
00558 
00559 #if defined(__mips__)
00560 
00561 #define MULADDC_INIT                            \
00562     asm( "lw     $10, %0        " :: "m" (s));  \
00563     asm( "lw     $11, %0        " :: "m" (d));  \
00564     asm( "lw     $12, %0        " :: "m" (c));  \
00565     asm( "lw     $13, %0        " :: "m" (b));
00566 
00567 #define MULADDC_CORE                            \
00568     asm( "lw     $14, 0($10)    " );            \
00569     asm( "multu  $13, $14       " );            \
00570     asm( "addi   $10, $10, 4    " );            \
00571     asm( "mflo   $14            " );            \
00572     asm( "mfhi   $9             " );            \
00573     asm( "addu   $14, $12, $14  " );            \
00574     asm( "lw     $15, 0($11)    " );            \
00575     asm( "sltu   $12, $14, $12  " );            \
00576     asm( "addu   $15, $14, $15  " );            \
00577     asm( "sltu   $14, $15, $14  " );            \
00578     asm( "addu   $12, $12, $9   " );            \
00579     asm( "sw     $15, 0($11)    " );            \
00580     asm( "addu   $12, $12, $14  " );            \
00581     asm( "addi   $11, $11, 4    " );
00582 
00583 #define MULADDC_STOP                            \
00584     asm( "sw     $12, %0        " : "=m" (c));  \
00585     asm( "sw     $11, %0        " : "=m" (d));  \
00586     asm( "sw     $10, %0        " : "=m" (s) :: \
00587     "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
00588 
00589 #endif /* MIPS */
00590 #endif /* GNUC */
00591 
00592 #if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
00593 
00594 #define MULADDC_INIT                            \
00595     __asm   mov     esi, s                      \
00596     __asm   mov     edi, d                      \
00597     __asm   mov     ecx, c                      \
00598     __asm   mov     ebx, b
00599 
00600 #define MULADDC_CORE                            \
00601     __asm   lodsd                               \
00602     __asm   mul     ebx                         \
00603     __asm   add     eax, ecx                    \
00604     __asm   adc     edx, 0                      \
00605     __asm   add     eax, [edi]                  \
00606     __asm   adc     edx, 0                      \
00607     __asm   mov     ecx, edx                    \
00608     __asm   stosd
00609 
00610 #if defined(POLARSSL_HAVE_SSE2)
00611 
00612 #define EMIT __asm _emit
00613 
00614 #define MULADDC_HUIT                            \
00615     EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
00616     EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
00617     EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
00618     EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
00619     EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
00620     EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
00621     EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
00622     EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
00623     EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
00624     EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
00625     EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
00626     EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
00627     EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
00628     EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
00629     EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
00630     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
00631     EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
00632     EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
00633     EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
00634     EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
00635     EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
00636     EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
00637     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00638     EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
00639     EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
00640     EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
00641     EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
00642     EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
00643     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
00644     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00645     EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
00646     EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
00647     EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
00648     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
00649     EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
00650     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
00651     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00652     EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
00653     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
00654     EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
00655     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
00656     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00657     EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
00658     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
00659     EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
00660     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
00661     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00662     EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
00663     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
00664     EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
00665     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
00666     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00667     EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
00668     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
00669     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00670     EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
00671     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
00672     EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
00673     EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
00674     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00675     EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
00676 
00677 #define MULADDC_STOP                            \
00678     EMIT 0x0F  EMIT 0x77                        \
00679     __asm   mov     c, ecx                      \
00680     __asm   mov     d, edi                      \
00681     __asm   mov     s, esi                      \
00682 
00683 #else
00684 
00685 #define MULADDC_STOP                            \
00686     __asm   mov     c, ecx                      \
00687     __asm   mov     d, edi                      \
00688     __asm   mov     s, esi                      \
00689 
00690 #endif /* SSE2 */
00691 #endif /* MSVC */
00692 
00693 #endif /* POLARSSL_HAVE_ASM */
00694 
00695 #if !defined(MULADDC_CORE)
00696 #if defined(POLARSSL_HAVE_LONGLONG)
00697 
00698 #define MULADDC_INIT                    \
00699 {                                       \
00700     t_udbl r;                           \
00701     t_uint r0, r1;
00702 
00703 #define MULADDC_CORE                    \
00704     r   = *(s++) * (t_udbl) b;           \
00705     r0  = r;                            \
00706     r1  = r >> biL;                     \
00707     r0 += c;  r1 += (r0 <  c);          \
00708     r0 += *d; r1 += (r0 < *d);          \
00709     c = r1; *(d++) = r0;
00710 
00711 #define MULADDC_STOP                    \
00712 }
00713 
00714 #else
00715 #define MULADDC_INIT                    \
00716 {                                       \
00717     t_uint s0, s1, b0, b1;              \
00718     t_uint r0, r1, rx, ry;              \
00719     b0 = ( b << biH ) >> biH;           \
00720     b1 = ( b >> biH );
00721 
00722 #define MULADDC_CORE                    \
00723     s0 = ( *s << biH ) >> biH;          \
00724     s1 = ( *s >> biH ); s++;            \
00725     rx = s0 * b1; r0 = s0 * b0;         \
00726     ry = s1 * b0; r1 = s1 * b1;         \
00727     r1 += ( rx >> biH );                \
00728     r1 += ( ry >> biH );                \
00729     rx <<= biH; ry <<= biH;             \
00730     r0 += rx; r1 += (r0 < rx);          \
00731     r0 += ry; r1 += (r0 < ry);          \
00732     r0 +=  c; r1 += (r0 <  c);          \
00733     r0 += *d; r1 += (r0 < *d);          \
00734     c = r1; *(d++) = r0;
00735 
00736 #define MULADDC_STOP                    \
00737 }
00738 
00739 #endif /* C (generic)  */
00740 #endif /* C (longlong) */
00741 
00742 #endif /* bn_mul.h */