mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bn_mul.h Source File

bn_mul.h

Go to the documentation of this file.
00001 /**
00002  * \file bn_mul.h
00003  *
00004  * \brief  Multi-precision integer library
00005  *
00006  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00007  *  SPDX-License-Identifier: Apache-2.0
00008  *
00009  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  *  not use this file except in compliance with the License.
00011  *  You may obtain a copy of the License at
00012  *
00013  *  http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  *  Unless required by applicable law or agreed to in writing, software
00016  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  *  See the License for the specific language governing permissions and
00019  *  limitations under the License.
00020  *
00021  *  This file is part of mbed TLS (https://tls.mbed.org)
00022  */
00023 /*
00024  *      Multiply source vector [s] with b, add result
00025  *       to destination vector [d] and set carry c.
00026  *
00027  *      Currently supports:
00028  *
00029  *         . IA-32 (386+)         . AMD64 / EM64T
00030  *         . IA-32 (SSE2)         . Motorola 68000
00031  *         . PowerPC, 32-bit      . MicroBlaze
00032  *         . PowerPC, 64-bit      . TriCore
00033  *         . SPARC v8             . ARM v3+
00034  *         . Alpha                . MIPS32
00035  *         . C, longlong          . C, generic
00036  */
00037 #ifndef MBEDTLS_BN_MUL_H
00038 #define MBEDTLS_BN_MUL_H
00039 
00040 #include "bignum.h"
00041 
00042 #if defined(MBEDTLS_HAVE_ASM)
00043 
00044 #ifndef asm
00045 #define asm __asm
00046 #endif
00047 
00048 /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
00049 #if defined(__GNUC__) && \
00050     ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
00051 #if defined(__i386__)
00052 
00053 #define MULADDC_INIT                        \
00054     asm(                                    \
00055         "movl   %%ebx, %0           \n\t"   \
00056         "movl   %5, %%esi           \n\t"   \
00057         "movl   %6, %%edi           \n\t"   \
00058         "movl   %7, %%ecx           \n\t"   \
00059         "movl   %8, %%ebx           \n\t"
00060 
00061 #define MULADDC_CORE                        \
00062         "lodsl                      \n\t"   \
00063         "mull   %%ebx               \n\t"   \
00064         "addl   %%ecx,   %%eax      \n\t"   \
00065         "adcl   $0,      %%edx      \n\t"   \
00066         "addl   (%%edi), %%eax      \n\t"   \
00067         "adcl   $0,      %%edx      \n\t"   \
00068         "movl   %%edx,   %%ecx      \n\t"   \
00069         "stosl                      \n\t"
00070 
00071 #if defined(MBEDTLS_HAVE_SSE2)
00072 
00073 #define MULADDC_HUIT                            \
00074         "movd     %%ecx,     %%mm1      \n\t"   \
00075         "movd     %%ebx,     %%mm0      \n\t"   \
00076         "movd     (%%edi),   %%mm3      \n\t"   \
00077         "paddq    %%mm3,     %%mm1      \n\t"   \
00078         "movd     (%%esi),   %%mm2      \n\t"   \
00079         "pmuludq  %%mm0,     %%mm2      \n\t"   \
00080         "movd     4(%%esi),  %%mm4      \n\t"   \
00081         "pmuludq  %%mm0,     %%mm4      \n\t"   \
00082         "movd     8(%%esi),  %%mm6      \n\t"   \
00083         "pmuludq  %%mm0,     %%mm6      \n\t"   \
00084         "movd     12(%%esi), %%mm7      \n\t"   \
00085         "pmuludq  %%mm0,     %%mm7      \n\t"   \
00086         "paddq    %%mm2,     %%mm1      \n\t"   \
00087         "movd     4(%%edi),  %%mm3      \n\t"   \
00088         "paddq    %%mm4,     %%mm3      \n\t"   \
00089         "movd     8(%%edi),  %%mm5      \n\t"   \
00090         "paddq    %%mm6,     %%mm5      \n\t"   \
00091         "movd     12(%%edi), %%mm4      \n\t"   \
00092         "paddq    %%mm4,     %%mm7      \n\t"   \
00093         "movd     %%mm1,     (%%edi)    \n\t"   \
00094         "movd     16(%%esi), %%mm2      \n\t"   \
00095         "pmuludq  %%mm0,     %%mm2      \n\t"   \
00096         "psrlq    $32,       %%mm1      \n\t"   \
00097         "movd     20(%%esi), %%mm4      \n\t"   \
00098         "pmuludq  %%mm0,     %%mm4      \n\t"   \
00099         "paddq    %%mm3,     %%mm1      \n\t"   \
00100         "movd     24(%%esi), %%mm6      \n\t"   \
00101         "pmuludq  %%mm0,     %%mm6      \n\t"   \
00102         "movd     %%mm1,     4(%%edi)   \n\t"   \
00103         "psrlq    $32,       %%mm1      \n\t"   \
00104         "movd     28(%%esi), %%mm3      \n\t"   \
00105         "pmuludq  %%mm0,     %%mm3      \n\t"   \
00106         "paddq    %%mm5,     %%mm1      \n\t"   \
00107         "movd     16(%%edi), %%mm5      \n\t"   \
00108         "paddq    %%mm5,     %%mm2      \n\t"   \
00109         "movd     %%mm1,     8(%%edi)   \n\t"   \
00110         "psrlq    $32,       %%mm1      \n\t"   \
00111         "paddq    %%mm7,     %%mm1      \n\t"   \
00112         "movd     20(%%edi), %%mm5      \n\t"   \
00113         "paddq    %%mm5,     %%mm4      \n\t"   \
00114         "movd     %%mm1,     12(%%edi)  \n\t"   \
00115         "psrlq    $32,       %%mm1      \n\t"   \
00116         "paddq    %%mm2,     %%mm1      \n\t"   \
00117         "movd     24(%%edi), %%mm5      \n\t"   \
00118         "paddq    %%mm5,     %%mm6      \n\t"   \
00119         "movd     %%mm1,     16(%%edi)  \n\t"   \
00120         "psrlq    $32,       %%mm1      \n\t"   \
00121         "paddq    %%mm4,     %%mm1      \n\t"   \
00122         "movd     28(%%edi), %%mm5      \n\t"   \
00123         "paddq    %%mm5,     %%mm3      \n\t"   \
00124         "movd     %%mm1,     20(%%edi)  \n\t"   \
00125         "psrlq    $32,       %%mm1      \n\t"   \
00126         "paddq    %%mm6,     %%mm1      \n\t"   \
00127         "movd     %%mm1,     24(%%edi)  \n\t"   \
00128         "psrlq    $32,       %%mm1      \n\t"   \
00129         "paddq    %%mm3,     %%mm1      \n\t"   \
00130         "movd     %%mm1,     28(%%edi)  \n\t"   \
00131         "addl     $32,       %%edi      \n\t"   \
00132         "addl     $32,       %%esi      \n\t"   \
00133         "psrlq    $32,       %%mm1      \n\t"   \
00134         "movd     %%mm1,     %%ecx      \n\t"
00135 
00136 #define MULADDC_STOP                    \
00137         "emms                   \n\t"   \
00138         "movl   %4, %%ebx       \n\t"   \
00139         "movl   %%ecx, %1       \n\t"   \
00140         "movl   %%edi, %2       \n\t"   \
00141         "movl   %%esi, %3       \n\t"   \
00142         : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
00143         : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
00144         : "eax", "ecx", "edx", "esi", "edi"             \
00145     );
00146 
00147 #else
00148 
00149 #define MULADDC_STOP                    \
00150         "movl   %4, %%ebx       \n\t"   \
00151         "movl   %%ecx, %1       \n\t"   \
00152         "movl   %%edi, %2       \n\t"   \
00153         "movl   %%esi, %3       \n\t"   \
00154         : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
00155         : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
00156         : "eax", "ecx", "edx", "esi", "edi"             \
00157     );
00158 #endif /* SSE2 */
00159 #endif /* i386 */
00160 
00161 #if defined(__amd64__) || defined (__x86_64__)
00162 
00163 #define MULADDC_INIT                        \
00164     asm(                                    \
00165         "movq   %3, %%rsi           \n\t"   \
00166         "movq   %4, %%rdi           \n\t"   \
00167         "movq   %5, %%rcx           \n\t"   \
00168         "movq   %6, %%rbx           \n\t"   \
00169         "xorq   %%r8, %%r8          \n\t"
00170 
00171 #define MULADDC_CORE                        \
00172         "movq   (%%rsi), %%rax      \n\t"   \
00173         "mulq   %%rbx               \n\t"   \
00174         "addq   $8,      %%rsi      \n\t"   \
00175         "addq   %%rcx,   %%rax      \n\t"   \
00176         "movq   %%r8,    %%rcx      \n\t"   \
00177         "adcq   $0,      %%rdx      \n\t"   \
00178         "nop                        \n\t"   \
00179         "addq   %%rax,   (%%rdi)    \n\t"   \
00180         "adcq   %%rdx,   %%rcx      \n\t"   \
00181         "addq   $8,      %%rdi      \n\t"
00182 
00183 #define MULADDC_STOP                        \
00184         "movq   %%rcx, %0           \n\t"   \
00185         "movq   %%rdi, %1           \n\t"   \
00186         "movq   %%rsi, %2           \n\t"   \
00187         : "=m" (c), "=m" (d), "=m" (s)                      \
00188         : "m" (s), "m" (d), "m" (c), "m" (b)                \
00189         : "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8"    \
00190     );
00191 
00192 #endif /* AMD64 */
00193 
00194 #if defined(__mc68020__) || defined(__mcpu32__)
00195 
00196 #define MULADDC_INIT                    \
00197     asm(                                \
00198         "movl   %3, %%a2        \n\t"   \
00199         "movl   %4, %%a3        \n\t"   \
00200         "movl   %5, %%d3        \n\t"   \
00201         "movl   %6, %%d2        \n\t"   \
00202         "moveq  #0, %%d0        \n\t"
00203 
00204 #define MULADDC_CORE                    \
00205         "movel  %%a2@+, %%d1    \n\t"   \
00206         "mulul  %%d2, %%d4:%%d1 \n\t"   \
00207         "addl   %%d3, %%d1      \n\t"   \
00208         "addxl  %%d0, %%d4      \n\t"   \
00209         "moveq  #0,   %%d3      \n\t"   \
00210         "addl   %%d1, %%a3@+    \n\t"   \
00211         "addxl  %%d4, %%d3      \n\t"
00212 
00213 #define MULADDC_STOP                    \
00214         "movl   %%d3, %0        \n\t"   \
00215         "movl   %%a3, %1        \n\t"   \
00216         "movl   %%a2, %2        \n\t"   \
00217         : "=m" (c), "=m" (d), "=m" (s)              \
00218         : "m" (s), "m" (d), "m" (c), "m" (b)        \
00219         : "d0", "d1", "d2", "d3", "d4", "a2", "a3"  \
00220     );
00221 
00222 #define MULADDC_HUIT                        \
00223         "movel  %%a2@+,  %%d1       \n\t"   \
00224         "mulul  %%d2,    %%d4:%%d1  \n\t"   \
00225         "addxl  %%d3,    %%d1       \n\t"   \
00226         "addxl  %%d0,    %%d4       \n\t"   \
00227         "addl   %%d1,    %%a3@+     \n\t"   \
00228         "movel  %%a2@+,  %%d1       \n\t"   \
00229         "mulul  %%d2,    %%d3:%%d1  \n\t"   \
00230         "addxl  %%d4,    %%d1       \n\t"   \
00231         "addxl  %%d0,    %%d3       \n\t"   \
00232         "addl   %%d1,    %%a3@+     \n\t"   \
00233         "movel  %%a2@+,  %%d1       \n\t"   \
00234         "mulul  %%d2,    %%d4:%%d1  \n\t"   \
00235         "addxl  %%d3,    %%d1       \n\t"   \
00236         "addxl  %%d0,    %%d4       \n\t"   \
00237         "addl   %%d1,    %%a3@+     \n\t"   \
00238         "movel  %%a2@+,  %%d1       \n\t"   \
00239         "mulul  %%d2,    %%d3:%%d1  \n\t"   \
00240         "addxl  %%d4,    %%d1       \n\t"   \
00241         "addxl  %%d0,    %%d3       \n\t"   \
00242         "addl   %%d1,    %%a3@+     \n\t"   \
00243         "movel  %%a2@+,  %%d1       \n\t"   \
00244         "mulul  %%d2,    %%d4:%%d1  \n\t"   \
00245         "addxl  %%d3,    %%d1       \n\t"   \
00246         "addxl  %%d0,    %%d4       \n\t"   \
00247         "addl   %%d1,    %%a3@+     \n\t"   \
00248         "movel  %%a2@+,  %%d1       \n\t"   \
00249         "mulul  %%d2,    %%d3:%%d1  \n\t"   \
00250         "addxl  %%d4,    %%d1       \n\t"   \
00251         "addxl  %%d0,    %%d3       \n\t"   \
00252         "addl   %%d1,    %%a3@+     \n\t"   \
00253         "movel  %%a2@+,  %%d1       \n\t"   \
00254         "mulul  %%d2,    %%d4:%%d1  \n\t"   \
00255         "addxl  %%d3,    %%d1       \n\t"   \
00256         "addxl  %%d0,    %%d4       \n\t"   \
00257         "addl   %%d1,    %%a3@+     \n\t"   \
00258         "movel  %%a2@+,  %%d1       \n\t"   \
00259         "mulul  %%d2,    %%d3:%%d1  \n\t"   \
00260         "addxl  %%d4,    %%d1       \n\t"   \
00261         "addxl  %%d0,    %%d3       \n\t"   \
00262         "addl   %%d1,    %%a3@+     \n\t"   \
00263         "addxl  %%d0,    %%d3       \n\t"
00264 
00265 #endif /* MC68000 */
00266 
00267 #if defined(__powerpc64__) || defined(__ppc64__)
00268 
00269 #if defined(__MACH__) && defined(__APPLE__)
00270 
00271 #define MULADDC_INIT                        \
00272     asm(                                    \
00273         "ld     r3, %3              \n\t"   \
00274         "ld     r4, %4              \n\t"   \
00275         "ld     r5, %5              \n\t"   \
00276         "ld     r6, %6              \n\t"   \
00277         "addi   r3, r3, -8          \n\t"   \
00278         "addi   r4, r4, -8          \n\t"   \
00279         "addic  r5, r5,  0          \n\t"
00280 
00281 #define MULADDC_CORE                        \
00282         "ldu    r7, 8(r3)           \n\t"   \
00283         "mulld  r8, r7, r6          \n\t"   \
00284         "mulhdu r9, r7, r6          \n\t"   \
00285         "adde   r8, r8, r5          \n\t"   \
00286         "ld     r7, 8(r4)           \n\t"   \
00287         "addze  r5, r9              \n\t"   \
00288         "addc   r8, r8, r7          \n\t"   \
00289         "stdu   r8, 8(r4)           \n\t"
00290 
00291 #define MULADDC_STOP                        \
00292         "addze  r5, r5              \n\t"   \
00293         "addi   r4, r4, 8           \n\t"   \
00294         "addi   r3, r3, 8           \n\t"   \
00295         "std    r5, %0              \n\t"   \
00296         "std    r4, %1              \n\t"   \
00297         "std    r3, %2              \n\t"   \
00298         : "=m" (c), "=m" (d), "=m" (s)              \
00299         : "m" (s), "m" (d), "m" (c), "m" (b)        \
00300         : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
00301     );
00302 
00303 
00304 #else /* __MACH__ && __APPLE__ */
00305 
00306 #define MULADDC_INIT                        \
00307     asm(                                    \
00308         "ld     %%r3, %3            \n\t"   \
00309         "ld     %%r4, %4            \n\t"   \
00310         "ld     %%r5, %5            \n\t"   \
00311         "ld     %%r6, %6            \n\t"   \
00312         "addi   %%r3, %%r3, -8      \n\t"   \
00313         "addi   %%r4, %%r4, -8      \n\t"   \
00314         "addic  %%r5, %%r5,  0      \n\t"
00315 
00316 #define MULADDC_CORE                        \
00317         "ldu    %%r7, 8(%%r3)       \n\t"   \
00318         "mulld  %%r8, %%r7, %%r6    \n\t"   \
00319         "mulhdu %%r9, %%r7, %%r6    \n\t"   \
00320         "adde   %%r8, %%r8, %%r5    \n\t"   \
00321         "ld     %%r7, 8(%%r4)       \n\t"   \
00322         "addze  %%r5, %%r9          \n\t"   \
00323         "addc   %%r8, %%r8, %%r7    \n\t"   \
00324         "stdu   %%r8, 8(%%r4)       \n\t"
00325 
00326 #define MULADDC_STOP                        \
00327         "addze  %%r5, %%r5          \n\t"   \
00328         "addi   %%r4, %%r4, 8       \n\t"   \
00329         "addi   %%r3, %%r3, 8       \n\t"   \
00330         "std    %%r5, %0            \n\t"   \
00331         "std    %%r4, %1            \n\t"   \
00332         "std    %%r3, %2            \n\t"   \
00333         : "=m" (c), "=m" (d), "=m" (s)              \
00334         : "m" (s), "m" (d), "m" (c), "m" (b)        \
00335         : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
00336     );
00337 
00338 #endif /* __MACH__ && __APPLE__ */
00339 
00340 #elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32  */
00341 
00342 #if defined(__MACH__) && defined(__APPLE__)
00343 
00344 #define MULADDC_INIT                    \
00345     asm(                                \
00346         "lwz    r3, %3          \n\t"   \
00347         "lwz    r4, %4          \n\t"   \
00348         "lwz    r5, %5          \n\t"   \
00349         "lwz    r6, %6          \n\t"   \
00350         "addi   r3, r3, -4      \n\t"   \
00351         "addi   r4, r4, -4      \n\t"   \
00352         "addic  r5, r5,  0      \n\t"
00353 
00354 #define MULADDC_CORE                    \
00355         "lwzu   r7, 4(r3)       \n\t"   \
00356         "mullw  r8, r7, r6      \n\t"   \
00357         "mulhwu r9, r7, r6      \n\t"   \
00358         "adde   r8, r8, r5      \n\t"   \
00359         "lwz    r7, 4(r4)       \n\t"   \
00360         "addze  r5, r9          \n\t"   \
00361         "addc   r8, r8, r7      \n\t"   \
00362         "stwu   r8, 4(r4)       \n\t"
00363 
00364 #define MULADDC_STOP                    \
00365         "addze  r5, r5          \n\t"   \
00366         "addi   r4, r4, 4       \n\t"   \
00367         "addi   r3, r3, 4       \n\t"   \
00368         "stw    r5, %0          \n\t"   \
00369         "stw    r4, %1          \n\t"   \
00370         "stw    r3, %2          \n\t"   \
00371         : "=m" (c), "=m" (d), "=m" (s)              \
00372         : "m" (s), "m" (d), "m" (c), "m" (b)        \
00373         : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
00374     );
00375 
00376 #else /* __MACH__ && __APPLE__ */
00377 
00378 #define MULADDC_INIT                        \
00379     asm(                                    \
00380         "lwz    %%r3, %3            \n\t"   \
00381         "lwz    %%r4, %4            \n\t"   \
00382         "lwz    %%r5, %5            \n\t"   \
00383         "lwz    %%r6, %6            \n\t"   \
00384         "addi   %%r3, %%r3, -4      \n\t"   \
00385         "addi   %%r4, %%r4, -4      \n\t"   \
00386         "addic  %%r5, %%r5,  0      \n\t"
00387 
00388 #define MULADDC_CORE                        \
00389         "lwzu   %%r7, 4(%%r3)       \n\t"   \
00390         "mullw  %%r8, %%r7, %%r6    \n\t"   \
00391         "mulhwu %%r9, %%r7, %%r6    \n\t"   \
00392         "adde   %%r8, %%r8, %%r5    \n\t"   \
00393         "lwz    %%r7, 4(%%r4)       \n\t"   \
00394         "addze  %%r5, %%r9          \n\t"   \
00395         "addc   %%r8, %%r8, %%r7    \n\t"   \
00396         "stwu   %%r8, 4(%%r4)       \n\t"
00397 
00398 #define MULADDC_STOP                        \
00399         "addze  %%r5, %%r5          \n\t"   \
00400         "addi   %%r4, %%r4, 4       \n\t"   \
00401         "addi   %%r3, %%r3, 4       \n\t"   \
00402         "stw    %%r5, %0            \n\t"   \
00403         "stw    %%r4, %1            \n\t"   \
00404         "stw    %%r3, %2            \n\t"   \
00405         : "=m" (c), "=m" (d), "=m" (s)              \
00406         : "m" (s), "m" (d), "m" (c), "m" (b)        \
00407         : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
00408     );
00409 
00410 #endif /* __MACH__ && __APPLE__ */
00411 
00412 #endif /* PPC32 */
00413 
00414 /*
00415  * The Sparc(64) assembly is reported to be broken.
00416  * Disable it for now, until we're able to fix it.
00417  */
00418 #if 0 && defined(__sparc__)
00419 #if defined(__sparc64__)
00420 
00421 #define MULADDC_INIT                                    \
00422     asm(                                                \
00423                 "ldx     %3, %%o0               \n\t"   \
00424                 "ldx     %4, %%o1               \n\t"   \
00425                 "ld      %5, %%o2               \n\t"   \
00426                 "ld      %6, %%o3               \n\t"
00427 
00428 #define MULADDC_CORE                                    \
00429                 "ld      [%%o0], %%o4           \n\t"   \
00430                 "inc     4, %%o0                \n\t"   \
00431                 "ld      [%%o1], %%o5           \n\t"   \
00432                 "umul    %%o3, %%o4, %%o4       \n\t"   \
00433                 "addcc   %%o4, %%o2, %%o4       \n\t"   \
00434                 "rd      %%y, %%g1              \n\t"   \
00435                 "addx    %%g1, 0, %%g1          \n\t"   \
00436                 "addcc   %%o4, %%o5, %%o4       \n\t"   \
00437                 "st      %%o4, [%%o1]           \n\t"   \
00438                 "addx    %%g1, 0, %%o2          \n\t"   \
00439                 "inc     4, %%o1                \n\t"
00440 
00441         #define MULADDC_STOP                            \
00442                 "st      %%o2, %0               \n\t"   \
00443                 "stx     %%o1, %1               \n\t"   \
00444                 "stx     %%o0, %2               \n\t"   \
00445         : "=m" (c), "=m" (d), "=m" (s)          \
00446         : "m" (s), "m" (d), "m" (c), "m" (b)    \
00447         : "g1", "o0", "o1", "o2", "o3", "o4",   \
00448           "o5"                                  \
00449         );
00450 
00451 #else /* __sparc64__ */
00452 
00453 #define MULADDC_INIT                                    \
00454     asm(                                                \
00455                 "ld      %3, %%o0               \n\t"   \
00456                 "ld      %4, %%o1               \n\t"   \
00457                 "ld      %5, %%o2               \n\t"   \
00458                 "ld      %6, %%o3               \n\t"
00459 
00460 #define MULADDC_CORE                                    \
00461                 "ld      [%%o0], %%o4           \n\t"   \
00462                 "inc     4, %%o0                \n\t"   \
00463                 "ld      [%%o1], %%o5           \n\t"   \
00464                 "umul    %%o3, %%o4, %%o4       \n\t"   \
00465                 "addcc   %%o4, %%o2, %%o4       \n\t"   \
00466                 "rd      %%y, %%g1              \n\t"   \
00467                 "addx    %%g1, 0, %%g1          \n\t"   \
00468                 "addcc   %%o4, %%o5, %%o4       \n\t"   \
00469                 "st      %%o4, [%%o1]           \n\t"   \
00470                 "addx    %%g1, 0, %%o2          \n\t"   \
00471                 "inc     4, %%o1                \n\t"
00472 
00473 #define MULADDC_STOP                                    \
00474                 "st      %%o2, %0               \n\t"   \
00475                 "st      %%o1, %1               \n\t"   \
00476                 "st      %%o0, %2               \n\t"   \
00477         : "=m" (c), "=m" (d), "=m" (s)          \
00478         : "m" (s), "m" (d), "m" (c), "m" (b)    \
00479         : "g1", "o0", "o1", "o2", "o3", "o4",   \
00480           "o5"                                  \
00481         );
00482 
00483 #endif /* __sparc64__ */
00484 #endif /* __sparc__ */
00485 
00486 #if defined(__microblaze__) || defined(microblaze)
00487 
00488 #define MULADDC_INIT                    \
00489     asm(                                \
00490         "lwi   r3,   %3         \n\t"   \
00491         "lwi   r4,   %4         \n\t"   \
00492         "lwi   r5,   %5         \n\t"   \
00493         "lwi   r6,   %6         \n\t"   \
00494         "andi  r7,   r6, 0xffff \n\t"   \
00495         "bsrli r6,   r6, 16     \n\t"
00496 
00497 #define MULADDC_CORE                    \
00498         "lhui  r8,   r3,   0    \n\t"   \
00499         "addi  r3,   r3,   2    \n\t"   \
00500         "lhui  r9,   r3,   0    \n\t"   \
00501         "addi  r3,   r3,   2    \n\t"   \
00502         "mul   r10,  r9,  r6    \n\t"   \
00503         "mul   r11,  r8,  r7    \n\t"   \
00504         "mul   r12,  r9,  r7    \n\t"   \
00505         "mul   r13,  r8,  r6    \n\t"   \
00506         "bsrli  r8, r10,  16    \n\t"   \
00507         "bsrli  r9, r11,  16    \n\t"   \
00508         "add   r13, r13,  r8    \n\t"   \
00509         "add   r13, r13,  r9    \n\t"   \
00510         "bslli r10, r10,  16    \n\t"   \
00511         "bslli r11, r11,  16    \n\t"   \
00512         "add   r12, r12, r10    \n\t"   \
00513         "addc  r13, r13,  r0    \n\t"   \
00514         "add   r12, r12, r11    \n\t"   \
00515         "addc  r13, r13,  r0    \n\t"   \
00516         "lwi   r10,  r4,   0    \n\t"   \
00517         "add   r12, r12, r10    \n\t"   \
00518         "addc  r13, r13,  r0    \n\t"   \
00519         "add   r12, r12,  r5    \n\t"   \
00520         "addc   r5, r13,  r0    \n\t"   \
00521         "swi   r12,  r4,   0    \n\t"   \
00522         "addi   r4,  r4,   4    \n\t"
00523 
00524 #define MULADDC_STOP                    \
00525         "swi   r5,   %0         \n\t"   \
00526         "swi   r4,   %1         \n\t"   \
00527         "swi   r3,   %2         \n\t"   \
00528         : "=m" (c), "=m" (d), "=m" (s)              \
00529         : "m" (s), "m" (d), "m" (c), "m" (b)        \
00530         : "r3", "r4"  "r5", "r6", "r7", "r8",       \
00531           "r9", "r10", "r11", "r12", "r13"          \
00532     );
00533 
00534 #endif /* MicroBlaze */
00535 
00536 #if defined(__tricore__)
00537 
00538 #define MULADDC_INIT                            \
00539     asm(                                        \
00540         "ld.a   %%a2, %3                \n\t"   \
00541         "ld.a   %%a3, %4                \n\t"   \
00542         "ld.w   %%d4, %5                \n\t"   \
00543         "ld.w   %%d1, %6                \n\t"   \
00544         "xor    %%d5, %%d5              \n\t"
00545 
00546 #define MULADDC_CORE                            \
00547         "ld.w   %%d0,   [%%a2+]         \n\t"   \
00548         "madd.u %%e2, %%e4, %%d0, %%d1  \n\t"   \
00549         "ld.w   %%d0,   [%%a3]          \n\t"   \
00550         "addx   %%d2,    %%d2,  %%d0    \n\t"   \
00551         "addc   %%d3,    %%d3,    0     \n\t"   \
00552         "mov    %%d4,    %%d3           \n\t"   \
00553         "st.w  [%%a3+],  %%d2           \n\t"
00554 
00555 #define MULADDC_STOP                            \
00556         "st.w   %0, %%d4                \n\t"   \
00557         "st.a   %1, %%a3                \n\t"   \
00558         "st.a   %2, %%a2                \n\t"   \
00559         : "=m" (c), "=m" (d), "=m" (s)          \
00560         : "m" (s), "m" (d), "m" (c), "m" (b)    \
00561         : "d0", "d1", "e2", "d4", "a2", "a3"    \
00562     );
00563 
00564 #endif /* TriCore */
00565 
00566 #if defined(__arm__)
00567 
00568 #if defined(__thumb__) && !defined(__thumb2__)
00569 
00570 #define MULADDC_INIT                                    \
00571     asm(                                                \
00572             "ldr    r0, %3                      \n\t"   \
00573             "ldr    r1, %4                      \n\t"   \
00574             "ldr    r2, %5                      \n\t"   \
00575             "ldr    r3, %6                      \n\t"   \
00576             "lsr    r7, r3, #16                 \n\t"   \
00577             "mov    r9, r7                      \n\t"   \
00578             "lsl    r7, r3, #16                 \n\t"   \
00579             "lsr    r7, r7, #16                 \n\t"   \
00580             "mov    r8, r7                      \n\t"
00581 
00582 #define MULADDC_CORE                                    \
00583             "ldmia  r0!, {r6}                   \n\t"   \
00584             "lsr    r7, r6, #16                 \n\t"   \
00585             "lsl    r6, r6, #16                 \n\t"   \
00586             "lsr    r6, r6, #16                 \n\t"   \
00587             "mov    r4, r8                      \n\t"   \
00588             "mul    r4, r6                      \n\t"   \
00589             "mov    r3, r9                      \n\t"   \
00590             "mul    r6, r3                      \n\t"   \
00591             "mov    r5, r9                      \n\t"   \
00592             "mul    r5, r7                      \n\t"   \
00593             "mov    r3, r8                      \n\t"   \
00594             "mul    r7, r3                      \n\t"   \
00595             "lsr    r3, r6, #16                 \n\t"   \
00596             "add    r5, r5, r3                  \n\t"   \
00597             "lsr    r3, r7, #16                 \n\t"   \
00598             "add    r5, r5, r3                  \n\t"   \
00599             "add    r4, r4, r2                  \n\t"   \
00600             "mov    r2, #0                      \n\t"   \
00601             "adc    r5, r2                      \n\t"   \
00602             "lsl    r3, r6, #16                 \n\t"   \
00603             "add    r4, r4, r3                  \n\t"   \
00604             "adc    r5, r2                      \n\t"   \
00605             "lsl    r3, r7, #16                 \n\t"   \
00606             "add    r4, r4, r3                  \n\t"   \
00607             "adc    r5, r2                      \n\t"   \
00608             "ldr    r3, [r1]                    \n\t"   \
00609             "add    r4, r4, r3                  \n\t"   \
00610             "adc    r2, r5                      \n\t"   \
00611             "stmia  r1!, {r4}                   \n\t"
00612 
00613 #define MULADDC_STOP                                    \
00614             "str    r2, %0                      \n\t"   \
00615             "str    r1, %1                      \n\t"   \
00616             "str    r0, %2                      \n\t"   \
00617          : "=m" (c),  "=m" (d), "=m" (s)        \
00618          : "m" (s), "m" (d), "m" (c), "m" (b)   \
00619          : "r0", "r1", "r2", "r3", "r4", "r5",  \
00620            "r6", "r7", "r8", "r9", "cc"         \
00621          );
00622 
00623 #else
00624 
00625 #define MULADDC_INIT                                    \
00626     asm(                                                \
00627             "ldr    r0, %3                      \n\t"   \
00628             "ldr    r1, %4                      \n\t"   \
00629             "ldr    r2, %5                      \n\t"   \
00630             "ldr    r3, %6                      \n\t"
00631 
00632 #define MULADDC_CORE                                    \
00633             "ldr    r4, [r0], #4                \n\t"   \
00634             "mov    r5, #0                      \n\t"   \
00635             "ldr    r6, [r1]                    \n\t"   \
00636             "umlal  r2, r5, r3, r4              \n\t"   \
00637             "adds   r7, r6, r2                  \n\t"   \
00638             "adc    r2, r5, #0                  \n\t"   \
00639             "str    r7, [r1], #4                \n\t"
00640 
00641 #define MULADDC_STOP                                    \
00642             "str    r2, %0                      \n\t"   \
00643             "str    r1, %1                      \n\t"   \
00644             "str    r0, %2                      \n\t"   \
00645          : "=m" (c),  "=m" (d), "=m" (s)        \
00646          : "m" (s), "m" (d), "m" (c), "m" (b)   \
00647          : "r0", "r1", "r2", "r3", "r4", "r5",  \
00648            "r6", "r7", "cc"                     \
00649          );
00650 
00651 #endif /* Thumb */
00652 
00653 #endif /* ARMv3 */
00654 
00655 #if defined(__alpha__)
00656 
00657 #define MULADDC_INIT                    \
00658     asm(                                \
00659         "ldq    $1, %3          \n\t"   \
00660         "ldq    $2, %4          \n\t"   \
00661         "ldq    $3, %5          \n\t"   \
00662         "ldq    $4, %6          \n\t"
00663 
00664 #define MULADDC_CORE                    \
00665         "ldq    $6,  0($1)      \n\t"   \
00666         "addq   $1,  8, $1      \n\t"   \
00667         "mulq   $6, $4, $7      \n\t"   \
00668         "umulh  $6, $4, $6      \n\t"   \
00669         "addq   $7, $3, $7      \n\t"   \
00670         "cmpult $7, $3, $3      \n\t"   \
00671         "ldq    $5,  0($2)      \n\t"   \
00672         "addq   $7, $5, $7      \n\t"   \
00673         "cmpult $7, $5, $5      \n\t"   \
00674         "stq    $7,  0($2)      \n\t"   \
00675         "addq   $2,  8, $2      \n\t"   \
00676         "addq   $6, $3, $3      \n\t"   \
00677         "addq   $5, $3, $3      \n\t"
00678 
00679 #define MULADDC_STOP                                    \
00680         "stq    $3, %0          \n\t"   \
00681         "stq    $2, %1          \n\t"   \
00682         "stq    $1, %2          \n\t"   \
00683         : "=m" (c), "=m" (d), "=m" (s)              \
00684         : "m" (s), "m" (d), "m" (c), "m" (b)        \
00685         : "$1", "$2", "$3", "$4", "$5", "$6", "$7"  \
00686     );
00687 #endif /* Alpha */
00688 
00689 #if defined(__mips__) && !defined(__mips64)
00690 
00691 #define MULADDC_INIT                    \
00692     asm(                                \
00693         "lw     $10, %3         \n\t"   \
00694         "lw     $11, %4         \n\t"   \
00695         "lw     $12, %5         \n\t"   \
00696         "lw     $13, %6         \n\t"
00697 
00698 #define MULADDC_CORE                    \
00699         "lw     $14, 0($10)     \n\t"   \
00700         "multu  $13, $14        \n\t"   \
00701         "addi   $10, $10, 4     \n\t"   \
00702         "mflo   $14             \n\t"   \
00703         "mfhi   $9              \n\t"   \
00704         "addu   $14, $12, $14   \n\t"   \
00705         "lw     $15, 0($11)     \n\t"   \
00706         "sltu   $12, $14, $12   \n\t"   \
00707         "addu   $15, $14, $15   \n\t"   \
00708         "sltu   $14, $15, $14   \n\t"   \
00709         "addu   $12, $12, $9    \n\t"   \
00710         "sw     $15, 0($11)     \n\t"   \
00711         "addu   $12, $12, $14   \n\t"   \
00712         "addi   $11, $11, 4     \n\t"
00713 
00714 #define MULADDC_STOP                    \
00715         "sw     $12, %0         \n\t"   \
00716         "sw     $11, %1         \n\t"   \
00717         "sw     $10, %2         \n\t"   \
00718         : "=m" (c), "=m" (d), "=m" (s)                      \
00719         : "m" (s), "m" (d), "m" (c), "m" (b)                \
00720         : "$9", "$10", "$11", "$12", "$13", "$14", "$15"    \
00721     );
00722 
00723 #endif /* MIPS */
00724 #endif /* GNUC */
00725 
00726 #if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
00727 
00728 #define MULADDC_INIT                            \
00729     __asm   mov     esi, s                      \
00730     __asm   mov     edi, d                      \
00731     __asm   mov     ecx, c                      \
00732     __asm   mov     ebx, b
00733 
00734 #define MULADDC_CORE                            \
00735     __asm   lodsd                               \
00736     __asm   mul     ebx                         \
00737     __asm   add     eax, ecx                    \
00738     __asm   adc     edx, 0                      \
00739     __asm   add     eax, [edi]                  \
00740     __asm   adc     edx, 0                      \
00741     __asm   mov     ecx, edx                    \
00742     __asm   stosd
00743 
00744 #if defined(MBEDTLS_HAVE_SSE2)
00745 
00746 #define EMIT __asm _emit
00747 
00748 #define MULADDC_HUIT                            \
00749     EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
00750     EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
00751     EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
00752     EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
00753     EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
00754     EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
00755     EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
00756     EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
00757     EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
00758     EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
00759     EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
00760     EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
00761     EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
00762     EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
00763     EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
00764     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
00765     EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
00766     EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
00767     EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
00768     EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
00769     EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
00770     EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
00771     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00772     EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
00773     EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
00774     EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
00775     EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
00776     EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
00777     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
00778     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00779     EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
00780     EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
00781     EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
00782     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
00783     EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
00784     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
00785     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00786     EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
00787     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
00788     EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
00789     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
00790     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00791     EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
00792     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
00793     EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
00794     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
00795     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00796     EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
00797     EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
00798     EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
00799     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
00800     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00801     EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
00802     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
00803     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00804     EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
00805     EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
00806     EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
00807     EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
00808     EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
00809     EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
00810 
00811 #define MULADDC_STOP                            \
00812     EMIT 0x0F  EMIT 0x77                        \
00813     __asm   mov     c, ecx                      \
00814     __asm   mov     d, edi                      \
00815     __asm   mov     s, esi                      \
00816 
00817 #else
00818 
00819 #define MULADDC_STOP                            \
00820     __asm   mov     c, ecx                      \
00821     __asm   mov     d, edi                      \
00822     __asm   mov     s, esi                      \
00823 
00824 #endif /* SSE2 */
00825 #endif /* MSVC */
00826 
00827 #endif /* MBEDTLS_HAVE_ASM */
00828 
00829 #if !defined(MULADDC_CORE)
00830 #if defined(MBEDTLS_HAVE_UDBL)
00831 
00832 #define MULADDC_INIT                    \
00833 {                                       \
00834     mbedtls_t_udbl r;                           \
00835     mbedtls_mpi_uint r0, r1;
00836 
00837 #define MULADDC_CORE                    \
00838     r   = *(s++) * (mbedtls_t_udbl) b;          \
00839     r0  = (mbedtls_mpi_uint) r;                   \
00840     r1  = (mbedtls_mpi_uint)( r >> biL );         \
00841     r0 += c;  r1 += (r0 <  c);          \
00842     r0 += *d; r1 += (r0 < *d);          \
00843     c = r1; *(d++) = r0;
00844 
00845 #define MULADDC_STOP                    \
00846 }
00847 
00848 #else
00849 #define MULADDC_INIT                    \
00850 {                                       \
00851     mbedtls_mpi_uint s0, s1, b0, b1;              \
00852     mbedtls_mpi_uint r0, r1, rx, ry;              \
00853     b0 = ( b << biH ) >> biH;           \
00854     b1 = ( b >> biH );
00855 
00856 #define MULADDC_CORE                    \
00857     s0 = ( *s << biH ) >> biH;          \
00858     s1 = ( *s >> biH ); s++;            \
00859     rx = s0 * b1; r0 = s0 * b0;         \
00860     ry = s1 * b0; r1 = s1 * b1;         \
00861     r1 += ( rx >> biH );                \
00862     r1 += ( ry >> biH );                \
00863     rx <<= biH; ry <<= biH;             \
00864     r0 += rx; r1 += (r0 < rx);          \
00865     r0 += ry; r1 += (r0 < ry);          \
00866     r0 +=  c; r1 += (r0 <  c);          \
00867     r0 += *d; r1 += (r0 < *d);          \
00868     c = r1; *(d++) = r0;
00869 
00870 #define MULADDC_STOP                    \
00871 }
00872 
00873 #endif /* C (generic)  */
00874 #endif /* C (longlong) */
00875 
00876 #endif /* bn_mul.h */